7. 파이썬gui 응용: gui 채팅프로그래밍 -...

25
순천향대학교 컴퓨터공학과 1 7. 파이썬 GUI 응용: GUI 채팅 프로그래밍 순천향대학교 컴퓨터공학과 이상정 GUI 설계기법 7. 파이썬 GUI 응용: GUI 채팅 학습 내용 GUI 채팅 프로그램 GUI 기반 채팅 프로그램 클라이언트와 서버가 하나의 프로그램 참조 사이트 Python Chat Program https://github.com/chprice/Python-Chat-Program 새로이 소개되는 파이썬 언어 기능 새로운 위젯: 프레임/Toplevel, 스크롤바, 메뉴 이벤트와 바인딩 파일 대화상자 클래스 기반 스레드 생성 람다 함수 (lambda function) 순천향대학교 컴퓨터공학과 2

Upload: others

Post on 17-Feb-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

순천향대학교 컴퓨터공학과 1

7. 파이썬 GUI 응용: GUI 채팅 프로그래밍

순천향대학교 컴퓨터공학과

이 상 정

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

학습 내용

GUI 채팅 프로그램• GUI 기반 채팅 프로그램

• 클라이언트와 서버가 하나의 프로그램

• 참조 사이트Python Chat Programhttps://github.com/chprice/Python-Chat-Program

새로이 소개되는 파이썬 언어 기능• 새로운 위젯: 프레임/Toplevel, 스크롤바, 메뉴

• 이벤트와 바인딩

• 파일 대화상자

• 클래스 기반 스레드 생성

• 람다 함수 (lambda function)

순천향대학교 컴퓨터공학과 2

Page 2: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

프레임/Topleve 위젯 (Frame Widget)

프레임 위젯은 다른 위젯을 포함(그룹화)하는 사각형 영역

• fr = Frame(app)

프레임 위젯에 버튼, Label 위젯 포함 예

app = Tk() # 윈도우 생성

fr = Frame(app) # 프레임 생성

Label(fr, text="Frame Label").pack() # Label 생성

Button(fr, text="frame test").pack() # Button 생성

Toplevel 위젯

• 프레임 위젯과 유사하나 윈도우가 부모 윈도우와 독립적으로 표시

순천향대학교 컴퓨터공학과 3

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

스크롤바 위젯 (Scrollbar Widget)

스크롤바 생성• sb = Scrollbar(app)

sb.pack(side=RIGHT, fill=Y)

• 오른쪽에 표시, 윈도우의 세로 방향에 채움

• fill 속성은 위젯을 공간(윈도우, 프레임) 전체에 채움을 표시

– 가로 채움 X, 세로 채움 Y, 모두 채움 BOTH

스크롤바는 다른 위젯(Text, ListBox, Canvas)과 연동하여동작• 텍스트 위젯과 연동 예

txt = Text(app) # 텍스트 위젯 생성sb.config(command=txt.yview)

# 스크롤바에 텍스트 위젯의 세로 방향 연동 지정txt.config(yscrollcommand=sb.set)

# 텍스트 위젯에 스크롤바 위젯의 세로 방향 연동 지정

순천향대학교 컴퓨터공학과 4

Page 3: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

이벤트와 바인딩 (Event and Binding)

GUI 프로그래밍은 이벤트 구동(event-driven) 방식 동작• 이벤트 루프에서 이벤트 기다림

이벤트 바인딩 (Binding)• 위젯의 이벤트를 사용자가 지정

• 이벤트와 이벤트 처리 함수 지정

• 이벤트 객체 인수 전달

• 모든 위젯은 bind 메서드를 사용하여 이벤트 처리 지정

• 엔트리 위젯에 리턴 키 누른 경우 dispalyText 함수 실행 예text_input = Entry(root, width=60) # 60 텍스트text_input.bind("<Return>", printText) # <Return> 이벤트 처리 지정text_input.pack()

def printText(event): # 이벤트 처리 함수, event 객체 인수

.....

순천향대학교 컴퓨터공학과 5

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

바인딩 이벤트 – 마우스

마우스 버튼 이벤트• <Button-1>, <Button-2> <Button-2>

• 마우스 버튼 클릭 이벤트 / 1 왼쪽 2 중간 3 오른쪽 버튼

• 위치 정보는 event 객체의 x, y 속성

• <B1-Motion>, <B2-Motion>, <B3-Motion>

• 마우스 버튼 드래그 (drag) 이벤트

• 위치 정보는 event 객체의 x, y 속성

• <ButtonRelease-1>, <ButtonRelease-2>, <ButtonRelease-3>

• 마우스 버튼 누름 해제 이벤트

• 위치 정보는 event 객체의 x, y 속성

• <Double-Button-1>, <Double-Button-2>, <Double-Button-3>

• 마우스 버튼 더블 클릭 이벤트

• <Enter> : 마우스 포인트가 위젯 상으로 이동 이벤트

• <Leave> : 마우스 포인트가 위젯을 벗어남 이벤트

순천향대학교 컴퓨터공학과 6

Page 4: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

바인딩 이벤트 – 키보드

키보드 이벤트• <Key>

• 임의 키 누름 이벤트

• 누른 키 값은 event 객체의 char 속성

• <Return> <Tab> <Escape> <Insert> <Delete> <Left> <Right> <Up> <Down> <F1> .........

• 특수 키 누름 이벤트

• a – z, 0 – 9, !, #, $, .......

• 키 누름 이벤트

• <Shift-Up>

• 시프트 키 누른 상태에서 위 화살표 누름 이벤트

• Alt, Shift, Control 등에 적용

• <Configure>

• 위젯의 크기 변동 이벤트

• 위젯의 크기는 이벤트 객체의 width, height 속성순천향대학교 컴퓨터공학과 7

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

프레임 예

엔트리 위젯에 입력된 값을 텍스트 위젯에 표시하는 예• 프레임에 텍스트 위젯과 스크롤바 위젯 포함

순천향대학교 컴퓨터공학과 8

Page 5: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 9

from tkinter import *

# Entry 위젯 이벤트 처리 함수

def displayText(event): # 이벤트 처ㅇ리 함수, event 객체 인수

data = etr.get() # Entry 위젯 텍스트 입력

frtext.config(state=NORMAL) # 텍스트 위젯 활성화 상태

frtext.insert(END, '₩n') # 다음 줄로 넘어감

frtext.insert(END, data) # 텍스트에 표시

frtext.yview(END) # 마지막 줄이 보이도록 지정

frtext.config(state=DISABLED) # 비활성화

etr.delete(0, END) # Entry 위젯의 텍스트 삭제

root = Tk()

root.title("Frame Example")

# 프레임 생성

fr = Frame(root)

# 텍스트 위젯 생성

frtext = Text(fr)

frtext.pack(side=LEFT, fill=Y)

프레임 예 코드 (1)

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

프레임 예 코드 (2)

순천향대학교 컴퓨터공학과 10

# 스크롤바 생성

frscroll = Scrollbar(fr)

frscroll.pack(side=RIGHT, fill=Y)

# 스크롤바와 텍스트 위젯 연동

frscroll.config(command=frtext.yview)

frtext.config(yscrollcommand=frscroll.set)

fr.pack()

# 텍스트에 첫 출력

frtext.insert(END, "환영합니다!")

frtext.config(state=DISABLED) # 텍스트 비활성화

# 입력 텍스트(엔트리) 위젯 객체 생성

etr = Entry(root, width=60)

# 엔트리 위젯 이벤트(엔터) 바인딩

etr.bind("<Return>", displayText)

etr.pack()

root.mainloop()

Page 6: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

파일 대화상자 (File Dialog)

파일을 오픈하고 저장하는 데 사용하는 대화상자(dialog)• tkinter.filedialog 모듈

• askopenfilename([oprions]) : 파일 오픈, 오픈된 파일이름 리턴

• asksaveasfilename([options]) : 파일 저장, 저장된 파일이름 리턴

• 옵션

• defaultextension : 저장 시 자동으로 지정되는 파일 확장자

• filetypes : (라벨, 패턴) 튜플 형식으로 파일 타입 지정

• title : 대화상자 타이틀

• initialdir : 초기 디렉토리

• initialfile : 저장 시 초기 파일

• parent : 대화상자 상위의 부모 윈도우

순천향대학교 컴퓨터공학과 11

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

파일 대화상자 예

파일 오픈 예from tkinter import *from tkinter.filedialog import *filename = askopenfilename(title="test", filetypes=[("텍스트", "*.txt")])

순천향대학교 컴퓨터공학과 12

Page 7: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

메뉴 위젯 (Menu Widget)

윈도우의 메뉴를 생성

메뉴 생성 절차• 메뉴바 생성: Menu()

app = Tk()menubar = Menu(app)app.configure(menu=menubar)

• 메뉴 생성: Menu() filemenu = Menu(menubar)

• 메뉴바에 메뉴 연결: add_cascade() 메서드menubar.add_cascade(label="File", menu=filemenu)

• 메뉴 항목 추가: add_command() 메서드filemenu.add_command(label="New", command=menu_new)filemenu.add_command(label="Open", command=menu_open)

순천향대학교 컴퓨터공학과 13

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

메뉴 프로그램 예

순천향대학교 컴퓨터공학과 14

from tkinter import *

# 메뉴 이벤트 처리 함수

def menu_new():

lb.config(text="New called")

def menu_open():

lb.config(text="Open called")

def menu_about():

lb.config(text="About called")

def menu_exit():

app.destroy()

app = Tk()

app.title("Menu Example")

# 메뉴바 생성

menubar = Menu(app)

app.config(menu=menubar)

# 메뉴 생성 및 메뉴바 연결

filemenu = Menu(menubar) # File 메뉴

menubar.add_cascade(label="File", menu=filemenu)

helpmenu = Menu(menubar) # Help 메뉴

menubar.add_cascade(label="Help", menu=helpmenu)

# 메뉴 항목 추가

filemenu.add_command(label="New", command=menu_new)

filemenu.add_command(label="Open", command=menu_open)

filemenu.add_separator() # 분리선 삽입

filemenu.add_command(label="Exit", command=menu_exit)

helpmenu.add_command(label="About",command=menu_about)

# 레이블 생성

lb = Label(app, text="hello, World!", width=50, height=3)

lb.pack()

app.mainloop()

Page 8: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

시험주행

순천향대학교 컴퓨터공학과 15

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

클래스 기반 스레드 생성

클래스 기반 스레드 생성• Thread 클래스로 부터 상속 받고 run() 메서드를 오버라이드

class userThread(threading.Thread):

....

# 스레드 오버라이드 메서드

def run(self):

....

# 스레드 생성 및 실행

th = userThread() # 객체 생성

th.start() # 스레드 실행 시작

순천향대학교 컴퓨터공학과 16

Page 9: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

클래스 기반 스레드 예

순천향대학교 컴퓨터공학과 17

import threading

class Mythread(threading.Thread):

m=0

n=0

# 생성자

def __init__(self, s, e=5):

threading.Thread.__init__(self)

self.m = s

self.n = e

# 스레드 오버라이드 메서드

def run(self):

for i in range(self.m, self.n):

print(" %d" %i)

# 스레드 생성 및 실행

th = Mythread(2) # 객체 생성

th.start() # # 스레드 실행

print("mainPrint ")

for i in range(100,106):

print(" %d" %i)

# 스레드 생성 및 실행

Mythread(30,35).start() # 스레드 실행

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

시험주행

순천향대학교 컴퓨터공학과 18

Page 10: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

람다 함수 (Lambda function)

람다 함수• 이름이 없는 한 줄 짜리 함수

lambda <인수들> : <반환할 식>

• 예f = lambda : 1x = f()g = lambda x, y : x + yy = g(1,2)print(x, y) # 1 3 출력

• 인수를 포함한 위젯의 이벤트 처리 함수 지정 시 사용

go = Button(app, text="시작", command=lambda: btclick(900, top))

순천향대학교 컴퓨터공학과 19

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 프로그램

GUI 기반 채팅 프로그램• 클라이언트와 서버가 하나의 프로그램

• 여러 개 윈도우 생성

• 메인 윈도우, 서버/클라이언트 연결 윈도우, 사용자 이름 지정 윈도우, 에러 윈도우

• 메인 윈도우

– 메인 스크린 텍스트 위젯, 스크롤바 위젯, 메시지 입력 엔트리위젯

– 서버/클라이언트 지정 라디오 버튼 위젯, 연결 버튼 위젯

• 서버/클라이언트 연결 윈도우

– IP 주소, 포트번호 입력 엔트리 위젯, 시작 버튼 위젯

• 사용자 이름 지정 윈도우

– 사용자 이름 입력 엔트리 위젯, 변경 버튼 위젯

• 에러 윈도우

– 에러 표시 라벨 위젯, OK 버튼 위젯

• 파일 저장 대화상자

순천향대학교 컴퓨터공학과 20

Page 11: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 - 서버 메인, 연결 윈도우

순천향대학교 컴퓨터공학과 21

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 - 클라이언트 메인, 연결 윈도우

순천향대학교 컴퓨터공학과 22

Page 12: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 23

GUI 기반 채팅 - 파일 메뉴,파일 저장 다이얼로그

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 - 파일 메뉴, 사용자 이름 지정/에러 표시 윈도우

순천향대학교 컴퓨터공학과 24

Page 13: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메뉴 생성

순천향대학교 컴퓨터공학과 25

# 루트 애플리케이션 윈도우 생성

root = Tk()

root.title("GUI 채팅")

# 메뉴바 생성

menubar = Menu(root)

root.config(menu=menubar)

# 파일 메뉴 생성 및 메뉴바 연결

file_menu = Menu(menubar, tearoff=0) # tearoff = 0, 점선표시 제거

menubar.add_cascade(label="파일", menu=file_menu)

# 파일 메뉴 항목 추가

file_menu.add_command(label="저장", command=lambda: saveHistory())

file_menu.add_command(label="사용자 이름",

command=lambda: username_options_window(root))

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메뉴, 저장 이벤트 함수

순천향대학교 컴퓨터공학과 26

def saveHistory():

# 파일 저장 대화상자 생성

file_name = asksaveasfilename(

title="채팅 내용 저장",

filetypes=[('Plain text', '*.txt'), ('Any File', '*.*')])

try:

filehandle = open(file_name + ".txt", "w")

except IOError:

print("채팅 내용 저장 실패.")

return

# 메인 스크린 텍스트 위젯 내용 읽기

contents = main_body_text.get(1.0, END)

# 각 라인 읽어들여 파일에 저장

for line in contents:

filehandle.write(line)

filehandle.close()

Page 14: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메뉴, 사용자 이름 지정 이벤트 함수 (1)

순천향대학교 컴퓨터공학과 27

# 사용자 이름 지정 옵션 윈도우 생성 함수

def username_options_window(master):

top = Toplevel(master)

top.title("사용자 이름 옵션")

top.grab_set() # 발생되는 이벤트를 현재 윈도우(Toplevel)에 한정

Label(top, text="사용자 이름:").grid(row=0)

name = Entry(top)

name.focus_set() # 키보드 입력 포커스

name.grid(row=0, column=1) # 0 행, 1열 그리드 배치

go = Button(top, text="변경", command=lambda:username_options_go(name.get(), top))

go.grid(row=1, column=0, columnspan=2, sticky=W+E) # 1행 중앙에 배치

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메뉴, 사용자 이름 지정 이벤트 함수 (2)

순천향대학교 컴퓨터공학과 28

# 사용자 이름 지정 이벤트 함수

def username_options_go(name, window):

for letter in [name]:

if letter == " " or letter == "₩n":

error_window(root, "잘못된 사용자 이름. 공백문자 허용 안됨.") # 에러 표시 윈도우 생성

return

global username

username = name

writeToScreen("변경된 사용자 이름: " + name, "시스템") # 메인 스크린 텍스트 위젯에 출력

window.destroy()

Page 15: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

grid 메서드

grid 메서드• pack 메서드와 같이 위젯을 공간(윈도우, 프레임, Toplevel)에 표시

• 공간을 2차원 테이블의 행(row), 열(column)로 분할하여 표시

• 옵션

• row, column : 행, 열 위치

• sticky : 셀 내의 정렬 위치 / S, N, E, W, NW SE …, W+E …….

• rowspan, columnspan: 여러 행, 열로 확장

• padx , pady : 수평, 수직 여백

순천향대학교 컴퓨터공학과 29

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메인 윈도우 (1)

순천향대학교 컴퓨터공학과 30

# 메인 디스플레이 프레임 생성

main_body = Frame(root)

# 메인 스크린 텍스트 위젯 생성

main_body_text = Text(main_body)

main_body_text.pack(side=LEFT, fill=Y)

# 스크롤바 위젯 객체 생성

body_text_scroll = Scrollbar(main_body)

body_text_scroll.pack(side=RIGHT, fill=Y)

# 스크롤바와 텍스트 위젯 연동

body_text_scroll.config(command=main_body_text.yview)

main_body_text.config(yscrollcommand=body_text_scroll.set)

main_body.pack()

# 텍스트에 환영 인사 출력

main_body_text.insert(END, "GUI 채팅, 환영합니다!")

main_body_text.config(state=DISABLED) # 텍스트 비활성화

Page 16: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메인 윈도우 (2)

순천향대학교 컴퓨터공학과 31

# 메시지 입력 엔트리 위젯 생성

text_input = Entry(root, width=60) # 너비 60(텍스트)

text_input.bind("<Return>", processUserText)

text_input.pack()

# 서버/클라이언트 지정 라디오 버튼 위젯 객체 생성

clientType = 1

Radiobutton(root, text="Client", variable=clientType,

value=0, command=toOne).pack(anchor=E)

Radiobutton(root, text="Server", variable=clientType,

value=1, command=toTwo).pack(anchor=E)

# 연결 버튼 위젯 생성

statusConnect = StringVar()

statusConnect.set("연결")

connecter = Button(root, textvariable=statusConnect,

command=lambda: connects(clientType))

connecter.pack()

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 텍스트 입출력

순천향대학교 컴퓨터공학과 32

def processUserText(event):

data = text_input.get() # 엔트리 메시지 입력

placeText(data) # 메인 스크린에 출력하고 전송

text_input.delete(0, END) # 입력 엔트리 클리어

# 텍스트를 스크린에 출력하고 상대방에게 전송

def placeText(text):

writeToScreen(text, username) # 메인 스크린에 출력

netThrow(connectionSocket, text) # 상대방에 메시지 전송

# 텍스트를 메인 스크린에 "[username] text" 형식으로 출력

def writeToScreen(text, username=""):

main_body_text.config(state=NORMAL) # 메인 스크린 활성화

main_body_text.insert(END, '₩n') # 개행문자 출력

if username:

main_body_text.insert(END, "[" + username + "] ") # 사용자 이름 출력

main_body_text.insert(END, text) # 메시지 출력

main_body_text.yview(END) # 수직 방향 뷰 변경 표시

main_body_text.config(state=DISABLED) # 메인 스크린 비활성화

Page 17: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 네트워크 송수신

순천향대학교 컴퓨터공학과 33

# 메시지 송수신 관련 함수

# 상대방(conn 소켓)에 메시지를 전송

def netThrow(conn, message):

try:

# 문자열 인코드하여 데이터 송신

conn.send(message.encode("utf8"))

except socket.error:

writeToScreen("메시지 송신 실패.", "시스템")

# conn 소켓에서 메시진 수신

def netCatch(conn):

try:

message = conn.recv(80)

return message.decode("utf8")

except socket.error:

writeToScreen("메시지 수신 실패.", "시스템")

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 연결 버튼 이벤트 함수

순천향대학교 컴퓨터공학과 34

# 연결 버튼 및 라디오 버튼 이벤트 관련 함수

# 연결 버튼 이벤트 함수

def connects(clientType):

connecter.config(state=DISABLED) # 버튼 비활성화

if clientType == 0: # 클라이언트

client_options_window(root)

if clientType == 1: # 서버

server_options_window(root)

# 클라이언트 라디오 버튼 이벤트 함수

def toOne():

global clientType

clientType = 0

# 서버 라디오 버튼 이벤트 함수

def toTwo():

global clientType

clientType = 1

Page 18: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 서버 연결 윈도우 (1)

순천향대학교 컴퓨터공학과 35

# 서버 포트 입력 윈도우 생성 함수

def server_options_window(master):

top = Toplevel(master)

top.title("서버 포트 연결 옵션")

top.grab_set() # 발생되는 이벤트를 현재 윈도우(Toplevel)에 한정

top.protocol("WM_DELETE_WINDOW", lambda: optionDelete(top))

Label(top, text="포트:").grid(row=0)

port = Entry(top)

port.grid(row=0, column=1)

port.focus_set()

go = Button(top, text="시작", command=lambda: server_options_go(port.get(), top))

go.grid(row=1, column=1)

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 서버 연결 윈도우 (2)

순천향대학교 컴퓨터공학과 36

# 서버 연결 처리 이벤트 함수

def server_options_go(port, window):

if options_sanitation(port): # 포트 입력 올바름 조사

window.destroy()

Server(int(port)).start() # 서버 스레드 실행 시작

# 윈도우 닫기 시 처리되는 함수

def optionDelete(window):

connecter.config(state=NORMAL) # 연결 버튼 활성화

window.destroy()

Page 19: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 클라이언트 연결 윈도우

순천향대학교 컴퓨터공학과 37

# 클라이언트의 서버 주소 입력 윈도우 생성 함수

def client_options_window(master):

top = Toplevel(master)

top.title("클라이언트 연결 옵션")

top.protocol("WM_DELETE_WINDOW", lambda: optionDelete(top))

top.grab_set() # 발생되는 이벤트를 현재 윈도우(Toplevel)에 한정

Label(top, text="서버 IP:").grid(row=0)

location = Entry(top)

location.grid(row=0, column=1)

location.focus_set()

Label(top, text="포트:").grid(row=1)

port = Entry(top)

port.grid(row=1, column=1)

go = Button(top, text="시작", command=lambda: client_options_go(location.get(), port.get(), top))

go.grid(row=2, column=1)

# 클라이언트 연결 처리 이벤트 함수

def client_options_go(dest, port, window):

if options_sanitation(port, dest): # IP 주소, 포트번호 올바름 조사

window.destroy()

Client(dest, int(port)).start() # 클라이언트 스레드 실행 시작

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 38

# 포트와 IP 주소의 올바름 검사 함수

def options_sanitation(por, loc=""):

if not por.isnumeric():

error_window(root, "포트 번호를 입력해주세요.")

return False

if int(por) < 0 or 65555 < int(por):

error_window(root, "0 과65555 사이 번호를 입력해주세요.")

return False

if loc != "":

if not ip_process(loc.split(".")):

error_window(root, "올바른 IP 주소를 입력해주세요.")

return False

return True

# 유효한 IP 주소인지를 검사 함수

def ip_process(ipArray):

if len(ipArray) != 4:

return False

for ip in ipArray:

if not ip.isnumeric():

return False

t = int(ip)

if t < 0 or 255 < t:

return False

return True

Page 20: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 스레드

클래스 기반 서버 스레드• Server 클래스에서 생성

• 서버 연결 윈도우에서 스레드 실행, Server(int(port)).start()

• TCP 서버 연결

• 메시지 수신 스레드 생성

클래스 기반 클라이언트 스레드• Client 클래스에서 생성

• 클라이언트 연결 윈도우에서 스레드 실행, Client(dest, int(port)).start()

• TCP 클라이언트 연결

• 메시지 수신 스레드 생성

메시지 수신 스레드 함수• Runner() 함수

• 메시지를 수신하여 메인 스크린 텍스트 위젯에 출력

순천향대학교 컴퓨터공학과 39

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 서버 클래스

순천향대학교 컴퓨터공학과 40

# Server 클래스: Thread 클래스 상속

class Server (threading.Thread):

# 생성자

def __init__(self, port):

threading.Thread.__init__(self) # 부모 클래스 생성자 호출

self.port = port # 포트 지정

def run(self):

global serv

# 서버 소켓 생성

serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

serv.bind(('', self.port)) # 주소와 소켓 결합

serv.listen(1) # 연결 요청 청취

global connectionSocket

writeToScreen("포트 " + str(self.port) + "에서 연결 대기 중 ....", "시스템")

# 연결 요청 수락, 연결 소켓 생성(클라이언트 IP 주소 받음)

connectionSocket, addr = serv.accept()

writeToScreen(str(addr[0]) + " 연결됨.", "시스템")

# 메시지 수신 스레드 생성

threading.Thread(target=Runner, args=(connectionSocket,str(addr[0]))).start()

Page 21: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 클라이언트 클래스

순천향대학교 컴퓨터공학과 41

# Client 클래스: Thread 클래스 상속

class Client (threading.Thread):

# 생성자

def __init__(self, host, port):

threading.Thread.__init__(self) # 부모 클래스 생성자 호출

self.port = port # 포트 지정

self.host = host # IP 주소 지정

def run(self):

global connectionSocket

# 소켓 생성connectionSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 서버에 연결 요청

connectionSocket.connect((self.host, self.port))

writeToScreen("IP 주소 " + self.host + ", 포트 " + str(self.port) + " 에 연결됨.", "시스템")

# 메시지 수신 스레드 생성

threading.Thread(target=Runner, args=(connectionSocket, self.host)).start()

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 – 메시지 수신 스레드 함수

순천향대학교 컴퓨터공학과 42

# 메시지 수신 스레드 함수

def Runner(conn, addr):

while 1:

data = netCatch(conn) # 메시지 수신

writeToScreen(data, addr)

Page 22: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

GUI 기반 채팅 코드

순천향대학교 컴퓨터공학과 43

from tkinter import *

from tkinter.filedialog import asksaveasfilename

import threading

import socket

# GLOBALS

username = "나"

connectionSocket = 0

# 메뉴 관련 함수

# 파일 대화상자 사용하여 채팅 내용 저장 함수

def saveHistory():

# 파일 저장 대화상자 생성

file_name = asksaveasfilename(

title="채팅 내용 저장",

filetypes=[('Plain text', '*.txt'), ('Any File', '*.*')])

try:

filehandle = open(file_name + ".txt", "w")

except IOError:

print("채팅 내용 저장 실패.")

return

# 메인 스크린 텍스트 위젯 내용 읽기

contents = main_body_text.get(1.0, END)

# 각 라인 읽어들여 파일에 저장

for line in contents:

filehandle.write(line)

filehandle.close()

# 사용자 이름 지정 옵션 윈도우 생성 함수

def username_options_window(master):

top = Toplevel(master)

top.title("사용자 이름 옵션")

top.grab_set() # 모든 이벤트를 현재 윈도우(Toplevel)에 한정

Label(top, text="사용자 이름:").grid(row=0)

name = Entry(top)

name.focus_set() # 키보드 입력 포커스

name.grid(row=0, column=1)

go = Button(top, text="변경", command=lambda:username_options_go(name.get(), top))

go.grid(row=1, column=0, columnspan=2, sticky=W+E) # 1행 중앙에 배치

# 사용자 이름 지정 이벤트 함수

def username_options_go(name, window):

for letter in [name]:

if letter == " " or letter == "₩n":

error_window(root, "잘못된 사용자 이름. 공백문자 허용 안됨.") # 에러 표시 윈도우 생성

return

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 44

global username

username = name

writeToScreen("변경된 사용자 이름: " + name, "시스템") # 메인 스크린 텍스트 위젯에 출력

window.destroy()

# 서버 연결 윈도우

# 서버 포트 입력 윈도우 생성 함수

def server_options_window(master):

top = Toplevel(master)

top.title("서버 포트 연결 옵션")

top.grab_set() # 발생 이벤트를 현재 윈도우에 한정

top.protocol("WM_DELETE_WINDOW", lambda: optionDelete(top))

Label(top, text="포트:").grid(row=0)

port = Entry(top)

port.grid(row=0, column=1)

port.focus_set()

go = Button(top, text="시작", command=lambda: server_options_go(port.get(), top))

go.grid(row=1, column=1)

# 서버 연결 처리 이벤트 함수

def server_options_go(port, window):

if options_sanitation(port): # 포트 입력 올바름 조사

window.destroy()

Server(int(port)).start() # 서버 스레드 실행 시작

# 윈도우 닫기 시 처리되는 함수

def optionDelete(window):

connecter.config(state=NORMAL) # 연결 버튼 활성화

window.destroy()

# 클라이언트 연결 윈도우

# 클라이언트의 서버 주소 입력 윈도우 생성 함수

def client_options_window(master):

top = Toplevel(master)

top.title("클라이언트 연결 옵션")

top.protocol("WM_DELETE_WINDOW", lambda: optionDelete(top))

top.grab_set() # 발생되는 이벤트를 현재 윈도우에 한정

Label(top, text="서버 IP:").grid(row=0)

location = Entry(top)

location.grid(row=0, column=1)

location.focus_set()

Label(top, text="포트:").grid(row=1)

port = Entry(top)

port.grid(row=1, column=1)

go = Button(top, text="시작", command=lambda:

client_options_go(location.get(), port.get(), top))

go.grid(row=2, column=1)

Page 23: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 45

# 클라이언트 연결 처리 이벤트 함수

def client_options_go(dest, port, window):

if options_sanitation(port, dest):

window.destroy()

Client(dest, int(port)).start() # 클라이언트 스레드 실행 시작

# 포트와 IP 주소의 올바름 검사 함수

def options_sanitation(por, loc=""):

if not por.isnumeric():

error_window(root, "포트 번호를 입력해주세요.")

return False

if int(por) < 0 or 65555 < int(por):

error_window(root, "0 과65555 사이 번호를 입력해주세요.")

return False

if loc != "":

if not ip_process(loc.split(".")):

error_window(root, "올바른 IP 주소를 입력해주세요.")

return False

return True

# 유효한 IP 주소인지를 검사 함수

def ip_process(ipArray):

if len(ipArray) != 4:

return False

for ip in ipArray:

if not ip.isnumeric():

return False

t = int(ip)

if t < 0 or 255 < t:

return False

return True

# 에러 표시 윈도우 생성 함수

def error_window(master, texty):

window = Toplevel(master)

window.title("에러")

window.grab_set()

Label(window, text=texty).pack()

go = Button(window, text="OK", command=window.destroy)

go.pack()

go.focus_set()

# 연결 버튼 및 라디오 버튼 이벤트 관련 함수

# 연결 버튼 이벤트 함수

def connects(clientType):

connecter.config(state=DISABLED) # 버튼 비활성화

if clientType == 0: # 클라이언트

client_options_window(root)

if clientType == 1: # 서버

server_options_window(root)

# 클라이언트 라디오 버튼 이벤트 함수

def toOne():

global clientType

clientType = 0

# 서버 라디오 버튼 이벤트 함수

def toTwo():

global clientType

clientType = 1

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 46

# 텍스트 입출력 관련 함수

# 엔트리 텍스트 입력 이벤트 함수

def processUserText(event):

data = text_input.get() # 엔트리 메시지 입력

placeText(data) # 메인 스크린에 출력하고 전송

text_input.delete(0, END) # 입력 엔트리 클리어

# 텍스트를 스크린에 출력하고 상대방에게 전송

def placeText(text):

writeToScreen(text, username) # 메인 스크린에 출력

netThrow(connectionSocket, text) # 상대방에 메시지 전송

# 텍스트를 메인 스크린에 "[username] text" 형식으로 출력

def writeToScreen(text, username=""):

main_body_text.config(state=NORMAL) # 메인 스트린 비활성화

main_body_text.insert(END, '₩n') # 개행문자 출력

if username:

main_body_text.insert(END, "[" + username + "] ") # 사용자 이름 출력

main_body_text.insert(END, text) # 메시지 출력

main_body_text.yview(END) # 수직 방향 뷰 변경 표시

main_body_text.config(state=DISABLED) # 메인 스크린 비활성화

# 메시지 송수신 관련 함수

# 상대방(conn 소켓)에 메시지를 전송

def netThrow(conn, message):

try:

# 문자열 인코드하여 데이터 송신

conn.send(message.encode("utf8"))

except socket.error:

writeToScreen("메시지 송신 실패.", "시스템")

# conn 소켓에서 메시진 수신

def netCatch(conn):

try:

message = conn.recv(80)

return message.decode("utf8")

except socket.error:

writeToScreen("메시지 수신 실패.", "시스템")

# Server 클래스: Thread 클래스 상속

class Server (threading.Thread):

# 생성자

def __init__(self, port):

threading.Thread.__init__(self) # 부모 클래스 생성자 호출

self.port = port # 포트 지정

def run(self):

global serv

# 서버 소켓 생성

serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

serv.bind(('', self.port)) # 주소와 소켓 결합

serv.listen(1) # 연결 요청 청취

global connectionSocket

writeToScreen("포트 " + str(self.port) +"에서 연결 대기 중 ....", "시스템")

Page 24: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 47

# 연결 요청 수락연결 소켓 생성, (클라이언트 IP 주소 받음)

connectionSocket, addr = serv.accept()

writeToScreen(str(addr[0]) + " 연결됨.", "시스템")

# 메시지 수신 스레드 생성

threading.Thread(target=Runner, args=(connectionSocket,str(addr[0]))).start()

# Client 클래스: Thread 클래스 상속

class Client (threading.Thread):

# 생성자

def __init__(self, host, port):

threading.Thread.__init__(self) # 부모 클래스 생성자 호출

self.port = port # 포트 지정

self.host = host # IP 주소 지정

def run(self):

global connectionSocket

# 소켓 생성

connectionSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 서버에 연결 요청

connectionSocket.connect((self.host, self.port))

writeToScreen("IP 주소 " + self.host + ", 포트 " + str(self.port) + " 에 연결됨.", "시스템")

# 메시지 수신 스레드 생성

threading.Thread(target=Runner, args=(connectionSocket, self.host)).start()

# 메시지 수신 스레드 함수

def Runner(conn, addr):

while 1:

data = netCatch(conn) # 메시지 수신

writeToScreen(data, addr)

# 루트 애플리케이션 윈도우 생성

root = Tk()

root.title("GUI 채팅")

# 메뉴바 생성

menubar = Menu(root)

root.config(menu=menubar)

# 파일 메뉴 생성 및 메뉴바 연결

file_menu = Menu(menubar, tearoff=0)# tearoff = 0, 점선표시 제거

menubar.add_cascade(label="파일", menu=file_menu)

# 파일 메뉴 항목 추가

file_menu.add_command(label="저장", command=lambda: saveHistory())

file_menu.add_command(label="사용자 이름",

command=lambda:username_options_window(root))

# 메인 디스플레이 프레임 생성

main_body = Frame(root)

# 메인 스크린 텍스트 위젯 생성

main_body_text = Text(main_body)

main_body_text.pack(side=LEFT, fill=Y)

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅순천향대학교 컴퓨터공학과 48

# 스크롤바 위젯 객체 생성

body_text_scroll = Scrollbar(main_body)

body_text_scroll.pack(side=RIGHT, fill=Y)

# 스크롤바와 텍스트 위젯 연동

body_text_scroll.config(command=main_body_text.yview)

main_body_text.config(yscrollcommand=body_text_scroll.set)

main_body.pack()

# 텍스트에 환영 인사 출력

main_body_text.insert(END, "GUI 채팅, 환영합니다!")

main_body_text.config(state=DISABLED) # 텍스트 비활성화

# 메시지 입력 엔트리 위젯 생성

text_input = Entry(root, width=60) # 너비 60(텍스트)

text_input.bind("<Return>", processUserText)

text_input.pack()

# 서버/클라이언트 지정 라디오 버튼 위젯 객체 생성

clientType = 1

Radiobutton(root, text="Client", variable=clientType,

value=0, command=toOne).pack(anchor=E)

Radiobutton(root, text="Server", variable=clientType,

value=1, command=toTwo).pack(anchor=E)

# 연결 버튼 위젯 생성

statusConnect = StringVar()

statusConnect.set("연결")

connecter = Button(root, textvariable=statusConnect,

command=lambda: connects(clientType))

connecter.pack()

root.mainloop()

Page 25: 7. 파이썬GUI 응용: GUI 채팅프로그래밍 - SCHcs.sch.ac.kr/lecture/Python/2017/GUI-2017/17-7-PythonGUI...GUI 설계기법 7. 파이썬GUI 응용: GUI 채팅 이벤트와바인딩(Eventand

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

과제

1. 앞에서 소개된 GUI 기반 채팅 프로그램을 작성하고 실행

2. 앞에서 배운 GUI 기반 채팅 프로그램의 기능을 추가한프로그램 작성프로그램 소스

• 기능 추가 예

• 연결 종료 메뉴

• 상대방 주소가 아닌 사용자 이름 표시

• 메뉴 추가 (연결 메뉴, 종료 메뉴, ……)

• 메시지 암호화

• 대화상대 관리…………

순천향대학교 컴퓨터공학과 49

GUI 설계기법

7. 파이썬 GUI 응용: GUI 채팅

참고 사이트

Python Chat Programhttps://github.com/chprice/Python-Chat-Program

• 다중 채팅 프로그램

• 대화 상대 관리

• 암호화

순천향대학교 컴퓨터공학과 50