2017년 하계 경성 프로그래밍 교육 (5/5) 경성대학교 공과대학 소프트웨어 학과
Tkinter 시작하기 간단한 예제로 Tkinter를 시작해보자 # tkinter의 모든 정의를 임포트한다. from tkinter import * # 창을 생성한다. window = Tk() # 레이블을 생성한다. label = Label(window, text = "파이썬에 오신것을 환영합니다.") # 버튼을 생성한다. button = Button(window, text = "저를 클릭해주세요") # 창 내부에 레이블을 배치한다. label.pack() # 창 내부에 버튼을 배치한다. button.pack() window.mainloop() # 이벤트 루프를 생성한다.
이벤트 처리하기 window.mainloop() # 이벤트 루프를 생성한다. 시작한다. 이벤트를 감지하고 처리한다. 메인창을 종료 아니오 예 종료한다.
이벤트 처리하기 - cont from tkinter import * # tkinter로부터 모든 정의를 임포트한다. def processOK(): print("OK 버튼이 클릭되었습니다.") def processCancel(): print("Cancel 버튼이 클릭되었습니다.") window = Tk() # 창을 생성한다. btOK = Button(window, text = "OK", fg = "red", command = processOK) btCancel = Button(window, text = "Cancel", bg = "yellow", command = processCancel) btOK.pack() # OK 버튼을 창 내부에 배치한다. btCancel.pack() # Cancel 버튼을 창 내부에 배치한다. window.mainloop() # 이벤트 루프를 생성한다.
위젯 데모 from tkinter import * # tkinter의 모든 정의를 임포트한다. class WidgetsDemo: def __init__(self): window = Tk() # 창을 생성한다. window.title("위젯 데모") # 제목을 설정한다. # 체크 버튼과 라디오 버튼을 frame1에 추가한다. frame1 = Frame(window) # 프레임을 생성하고 창에 추가한다. frame1.pack() self.v1 = IntVar() cbtBold = Checkbutton(frame1, text = "굵게", variable = self.v1, command = self.processCheckbutton) self.v2 = IntVar() rbRed = Radiobutton(frame1, text = "빨간색", bg = "red", variable = self.v2, value = 1, command = self.processRadiobutton) rbYellow = Radiobutton(frame1, text = "노란색", bg = "yellow", variable = self.v2, value = 2, cbtBold.grid(row = 1, column = 1) rbRed.grid(row = 1, column = 2) rbYellow.grid(row = 1, column = 3)
위젯 데모 - cont # 레이블, 엔트리, 버튼, 메시지를 frame2에 추가한다. frame2 = Frame(window) # 프레임을 생성하고 창에 추가한다. frame2.pack() label = Label(frame2, text = "이름을 입력하세요: ") self.name = StringVar() entryName = Entry(frame2, textvariable = self.name) btGetName = Button(frame2, text = "이름 가져오기, command = self.processButton) message = Message(frame2, text = "위젯 데모입니다.") label.grid(row = 1, column = 1) entryName.grid(row = 1, column = 2) btGetName.grid(row = 1, column = 3) message.grid(row = 1, column = 4) # 텍스트를 추가한다. text = Text(window) # 텍스트를 생성하고 창에 추가한다. text.pack() text.insert(END, "팁\nTkinter를 학습하는 최고의 방법은 잘 짜여진 ") "예제를 세세히 읽고 애플리케이션을 생성하는데 ") text.insert(END, "직접 사용해 보는 것이다.") window.mainloop() # 이벤트 루프를 생성한다.
위젯 데모 - cont def processCheckbutton(self): print("체크 버튼이 " + ("선택되었습니다. " if self.v1.get() == 1 else "해제되었습니다.")) def processRadiobutton(self): print(("빨간색" if self.v2.get() == 1 else "노란색") + " 이 선택되었습니다." ) def processButton(self): print("당신의 이름은 " + self.name.get() + "입니다.") WidgetsDemo() # GUI를 생성한다.
캔버스 데모 from tkinter import * # tkinter의 모든 정의를 임포트한다. class CanvasDemo: def __init__(self): window = Tk() # 창을 생성한다. window.title("캔버스 데모") # 제목을 설정한다. # 창에 캔버스를 배치한다. self.canvas = Canvas(window, width = 200, height = 100, bg = "white") self.canvas.pack() # 프레임에 버튼을 배치한다. frame = Frame(window) frame.pack() btRectangle = Button(frame, text = "직사각형", command = self.displayRect) btOval = Button(frame, text = "타원", command = self.displayOval) btArc = Button(frame, text = "호", command = self.displayArc) btPolygon = Button(frame, text = "다각형", command = self.displayPolygon) btLine = Button(frame, text = "선분", command = self.displayLine) btString = Button(frame, text = "문자열", command = self.displayString) btClear = Button(frame, text = "삭제하기", command = self.clearCanvas)
캔버스 데모 - cont btRectangle.grid(row = 1, column = 1) btOval.grid(row = 1, column = 2) btArc.grid(row = 1, column = 3) btPolygon.grid(row = 1, column = 4) btLine.grid(row = 1, column = 5) btString.grid(row = 1, column = 6) btClear.grid(row = 1, column = 7) window.mainloop() # 이벤트 루프를 생성한다. # 직사각형을 출력한다. def displayRect(self): self.canvas.create_rectangle(10, 10, 190, 90, tags = "rect") # 타원을 출력한다. def displayOval(self): self.canvas.create_oval(10, 10, 190, 90, fill = "red", tags = "oval") # 호를 출력한다. def displayArc(self): self.canvas.create_arc(10, 10, 190, 90, start = 0, extent = 90, width = 8, fill = "red", tags = "arc")
캔버스 데모 - cont # 다각형을 출력한다. def displayPolygon(self): self.canvas.create_polygon(10, 10, 190, 90, 30, 50, tags = "polygon") # 선분을 출력한다. def displayLine(self): self.canvas.create_line(10, 10, 190, 90, fill = "red", tags = "line") self.canvas.create_line(10, 90, 190, 10, width = 9, arrow = "last", activefill = "blue", tags = "line") # 문자열을 출력한다. def displayString(self): self.canvas.create_text(85, 40, text = "안녕 나는 문자열이야", font = "굴림 10 bold underline", tags = "string") # 도형을 삭제한다. def clearCanvas(self): self.canvas.delete("rect", "oval", "arc", "polygon", "line", "string") CanvasDemo() # GUI 생성한다.
기하 관리자 그리드 관리자 팩 관리자 위치 관리자 각각의 관리자는 위젯을 배치하는 독자적인 스타일이 있기 때문에 동일한 컨테이너에서 위젯 배치를 위해 여러 관리자를 혼용하는 것은 좋은 연습방법이 아니다. 의도한 배치를 얻기 위해서는 프레임을 하위 컨테이너로 사용할 수 있다.
팩 관리자 from tkinter import * # tkinter의 모든 정의를 임포트한다. class PackManagerDemo: def __init__(self): window = Tk() # 창을 생성한다. window.title("팩 관리자 데모 1") # 제목을 설정한다. Label(window, text = "파랑", bg = "blue").pack(side=LEFT) Label(window, text = "빨강", bg = "red").pack( side=LEFT, fill = BOTH, expand = 1) Label(window, text = "초록", bg = "green").pack( side=LEFT, fill = BOTH) window.mainloop() # 이벤트 루프를 생성한다. PackManagerDemo() # GUI를 생성한다.
그리드 관리자 from tkinter import * # tkinter의 모든 정의를 임포트한다. class GridManagerDemo: window = Tk() # 창을 생성한다. window.title("그리드 관리자 데모") # 제목을 설정한다. message = Message(window, text = "이 메시지 위젯은 3개의 행과 2개의 열을 차지한다.") message.grid(row = 1, column = 1, rowspan = 3, columnspan = 2) Label(window, text = "이름:").grid(row = 1, column = 3) Entry(window).grid(row = 1, column = 4, padx = 5, pady = 5) Label(window, text = "성:").grid(row = 2, column = 3) Entry(window).grid(row = 2, column = 4) Button(window, text = "이름 가져오기").grid(row = 3, padx = 5, pady = 5, column = 4, sticky = E) window.mainloop() # 이벤트 루프를 생성한다. GridManagerDemo() # GUI를 생성한다.
위치 관리자 from tkinter import * # tkinter의 모든 정의를 임포트한다. class PlaceManagerDemo: def __init__(self): window = Tk() # 창을 생성한다. window.title("위치 관리자 데모") # 제목을 설정한다. Label(window, text = "파랑", bg = "blue").place( x = 20, y = 20) Label(window, text = "빨강", bg = "red").place( x = 50, y = 50) Label(window, text = "초록", bg = "green").place( x = 80, y = 80) window.mainloop() # 이벤트 루프를 생성한다. PlaceManagerDemo() # GUI를 생성한다.
이미지 출력하기 레이블, 버튼, 체크 버튼, 또는 라디오 버튼에 이미지를 추가할 수 있다. 이미지를 생성하기 위해서 다음과 같이 PhotoImage 클래스를 사용한다: 이미지 파일은 반드시 GIF 형식으로 작성되어야만 한다. 다른 형식으로 작성된 이미지 파일을 GIF 형식으로 변환하기 위해서는 변환 유틸리티를 사용해야 한다. photo = PhotoImage(file = 이미지 파일명)
이미지 데모 from tkinter import * # tkinter의 모든 정의를 임포트한다. class ImageDemo: def __init__(self): window = Tk() # 창을 생성한다. window.title("이미지 데모") # 제목을 설정한다. # PhotoImage 객체를 생성한다. koreaImage = PhotoImage(file = "image/korea.gif") chinaImage = PhotoImage(file = "image/china.gif") leftImage = PhotoImage(file = "image/left.gif") rightImage = PhotoImage(file = "image/right.gif") usImage = PhotoImage(file = "image/usIcon.gif") ukImage = PhotoImage(file = "image/ukIcon.gif") crossImage = PhotoImage(file = "image/x.gif") circleImage = PhotoImage(file = "image/o.gif") # frame1은 레이블과 캔버스를 포함한다. frame1 = Frame(window) frame1.pack() Label(frame1, image = koreaImage).pack(side = LEFT) canvas = Canvas(frame1) 파일이 있어야 함
이미지 데모 - cont canvas.create_image(90, 50, image = chinaImage) canvas["width"] = 200 canvas["height"] = 100 canvas.pack(side = LEFT) # frame2는 버튼, 체크 버튼, 라디오 버튼을 포함한다. frame2 = Frame(window) frame2.pack() Button(frame2, image = leftImage).pack(side = LEFT) Button(frame2, image = rightImage).pack(side = LEFT) Checkbutton(frame2, image = usImage).pack(side = LEFT) Checkbutton(frame2, image = ukImage).pack(side = LEFT) Radiobutton(frame2, image = crossImage).pack(side = LEFT) Radiobutton(frame2, image = circleImage).pack(side = LEFT) window.mainloop() # 이벤트 루프를 생성한다. ImageDemo() # GUI를 생성한다.
메뉴 – 사례연구 : 계산기 Tkinter는 그래픽 사용자 인터페이스 생성을 위한 종합적인 해결방법을 제공한다. from tkinter import * class MenuDemo: def __init__(self): window = Tk() window.title("메뉴 데모") # 메뉴 바를 생성한다. menubar = Menu(window) window.config(menu = menubar) # 메뉴 바를 출력한다.
사례연구 : 계산기 - cont # 풀다운 메뉴를 생성하고, 메뉴 바에 추가한다. operationMenu = Menu(menubar, tearoff = 0) menubar.add_cascade(label = "연산", menu = operationMenu) operationMenu.add_command(label = "더하기", command = self.add) operationMenu.add_command(label = "빼기", command = self.subtract) operationMenu.add_separator() operationMenu.add_command(label = "곱하기", command = self.multiply) operationMenu.add_command(label = "나누기", command = self.divide) # 추가적인 풀다운 메뉴를 생성한다. exitmenu = Menu(menubar, tearoff = 0) menubar.add_cascade(label = "나가기", menu = exitmenu) exitmenu.add_command(label = "종료하기", command = quit) # 퉆바 프레임을 추가한다. frame0 = Frame(window) # 프레임을 생성하고 창에 추가한다. frame0.grid(row = 1, column = 1, sticky = W)
사례연구 : 계산기 - cont # 이미지를 생성한다. plusImage = PhotoImage(file = "image/plus.gif") minusImage = PhotoImage(file = "image/minus.gif") timesImage = PhotoImage(file = "image/times.gif") divideImage = PhotoImage(file = "image/divide.gif") Button(frame0, image = plusImage, command = self.add).grid(row = 1, column = 1, sticky = W) Button(frame0, image = minusImage, command = self.subtract).grid(row = 1, column = 2) Button(frame0, image = timesImage, command = self.multiply).grid(row = 1, column = 3) Button(frame0, image = divideImage, command = self.divide).grid(row = 1, column = 4) # 레이블과 엔트리를 frame1에 추가한다. frame1 = Frame(window) frame1.grid(row = 2, column = 1, pady = 10) Label(frame1, text = "숫자 1:").pack(side = LEFT) self.v1 = StringVar() Entry(frame1, width = 5, textvariable = self.v1, justify = RIGHT).pack(side = LEFT)
사례연구 : 계산기 - cont Label(frame1, text = "숫자 2:").pack(side = LEFT) self.v2 = StringVar() Entry(frame1, width = 5, textvariable = self.v2, justify = RIGHT).pack(side = LEFT) Label(frame1, text = "결과:").pack(side = LEFT) self.v3 = StringVar() Entry(frame1, width = 5, textvariable = self.v3, justify = RIGHT).pack(side = LEFT) # 버튼을 frame2에 추가한다. frame2 = Frame(window) # 프레임을 생성하고 창에 추가한다. frame2.grid(row = 3, column = 1, pady = 10, sticky = E) Button(frame2, text = "더하기", command = self.add).pack(side = LEFT) Button(frame2, text = "빼기", command = self.subtract).pack(side = LEFT) Button(frame2, text = "곱하기", command = self.multiply).pack(side = LEFT) Button(frame2, text = "나누기", command = self.divide).pack(side = LEFT) mainloop()
사례연구 : 계산기 - cont def add(self): self.v3.set(eval(self.v1.get()) + eval(self.v2.get())) def subtract(self): self.v3.set(eval(self.v1.get()) - eval(self.v2.get())) def multiply(self): self.v3.set(eval(self.v1.get()) * eval(self.v2.get())) def divide(self): self.v3.set(eval(self.v1.get()) / eval(self.v2.get())) MenuDemo()
사례연구 : 공 튕기기 # tkinter의 모든 정의를 임포트한다. from tkinter import * Ball x: int y: int dx: int dy: int color: Color radius: int 공 중심에 대한 x, y 좌표 기본값은 (0, 0) dx와 dy는 (x, y)에 대한 증가값 공의 색상 공의 반지름 # tkinter의 모든 정의를 임포트한다. from tkinter import * from random import randint # #RRGGBB 형식의 랜덤 색상 문자열을 반환한다. def getRandomColor(): color = "#" for j in range(6): color += toHexChar(randint(0, 15)) # 랜덤 숫자를 더한다. return color # 정수를 16진수 한 자리 문자로 변환한다. def toHexChar(hexValue): if 0 <= hexValue <= 9: return chr(hexValue + ord('0')) else: # 10 <= hexValue <= 15 return chr(hexValue - 10 + ord('A'))
사례연구 : 공 튕기기 – cont # Ball 클래스를 정의한다. class Ball: def __init__(self): self.x = 0 # 시작 중심 위치 self.y = 0 self.dx = 2 # 기본값 만큼 오른쪽으로 이동한다. self.dy = 2 # 기본값 만큼 아래로 이동한다. self.radius = 3 # 반지름은 고정되어 있다. self.color = getRandomColor() # 랜덤 색상을 얻는다. class BounceBalls: self.ballList = [] # 공 리스트를 생성한다. window = Tk() # 윈도우를 생성한다. window.title("공 튕기기") # 제목을 설정한다. self.width = 350 # self.canvas의 폭 self.height = 150 # self.canvas의 높이 self.canvas = Canvas(window, bg = "white", width = self.width, height = self.height) self.canvas.pack()
사례연구 : 공 튕기기 – cont frame = Frame(window) frame.pack() btStop = Button(frame, text = "정지", command = self.stop) btStop.pack(side = LEFT) btResume = Button(frame, text = "다시시작", command = self.resume) btResume.pack(side = LEFT) btAdd = Button(frame, text = "+", command = self.add) btAdd.pack(side = LEFT) btRemove = Button(frame, text = "-", command = self.remove) btRemove.pack(side = LEFT) self.sleepTime = 100 # 슬립 시간을 설정한다. self.isStopped = False self.animate() window.mainloop() # 이벤트 루프를 생성한다. def stop(self): # 애니메이션을 정지한다. self.isStopped = True def resume(self): # 애니메이션을 다시시작한다.
사례연구 : 공 튕기기 – cont def add(self): # 새로운 공을 추가한다. self.ballList.append(Ball()) def remove(self): # 마지막 공을 제거한다. self.ballList.pop() # 공의 움직임을 애니메이션한다. def animate(self): while not self.isStopped: # 슬립 self.canvas.after(self.sleepTime) # self.canvas 업데이터한다. self.canvas.update() self.canvas.delete("ball") for ball in self.ballList: self.redisplayBall(ball) def redisplayBall(self, ball): if ball.x > self.width or ball.x < 0: ball.dx = -ball.dx if ball.y > self.height or ball.y < 0: ball.dy = -ball.dy ball.x += ball.dx ball.y += ball.dy self.canvas.create_oval(ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius, fill = ball.color, tags = "ball") BounceBalls() # GUI를 생성한다.
Reference 파이썬, Y.Daniel Liang 저, 길준민, 정재화 역, 생능출판 Introduction to Programming Using Python, Y. Daniel Liang 저자 사이트 : http://www.cs.armstrong.edu/liang/py/