Tcl(tool command language)/Tk, tkinter

- Tcl :  웹, 데스트탑 어플, 네트워크, 테스팅 등 다양한 용도로 동적 프로그래밍 하기 좋은 언어

- Tk : GUI 라이브러리 제공하는 툴킷

- tkinter : Tcl/Tk 파이썬 레퍼로 tkinter 패키지로 gui 프로그래밍

 

 

1. tkinter window 관리 예제

- 윈도우 만들고, 크기 고정하고, X 누르면 메시지박스, iconify 버튼으로 아이콘화, quit버튼으로 종료

import tkinter
from tkinter import *
from tkinter import messagebox

global window

window = Tk()
window.title("window = Tk()")
window.geometry("300x300+100+100")
window.resizable(width=False, height = False)

def ask_quit():
    result = messagebox.askquestion("Msg", "quit?")
    if result == "yes":
        window.destroy()

label = Label(window, text="Buttons")
label.pack() # pack()윈도우에 배치
iconBtn = Button(window, text="iconify", command=window.iconify) #iconify 아이콘화
iconBtn.pack()
quitBtn = Button(window, text="quit", command=window.destroy)
quitBtn.pack()

window.protocol("WM_DELETE_WINDOW", ask_quit)
window.mainloop()

 

 

tkinter의 widget(window gadget) 클래스 

- tkinter의 위젯으로 frame, canvas가 있다.

- 하나의 윈도우에는 여러 프레임을 넣을 수 있다.

- 각 프레임에는 여러 캔버스를 넣을 수 있다.

- 각 캔버스에는 여러 라벨과 버튼 등의 위젯을 넣을 수 있다.

 

위젯 종류

- entry : 문자열 입력 공간

- scale : 슬라이드로 설정

- menu : 팝업 팝다운 메뉴

- 등

 

https://m.blog.naver.com/sisosw/221408280038

 

 

 

2. 윈도우 안에 프레임과 캔버스 그리기

import tkinter
from tkinter import *

window = Tk()
window.title("window - tk()")
window.geometry("600x600+200+100")
window.resizable(width=False, height=False)



frame1 = Frame(window, bg="light green", cursor="heart", bd=5, padx=10, pady=10, relief=GROOVE) #relief 프레임 기본 스타일
#relief : flat(기본), raised(버튼올린모양), sunken(버튼눌린모양), groove, ridge 등(대문자)
frame1.grid(row=0,column=0)
frame2 = Frame(window, bg="yellow", cursor="man", bd=5, padx=10, pady=10, relief=GROOVE)
frame2.grid(row=1,column=0)
frame3 = Frame(window, bg="yellow", cursor="plus", bd=5, padx=10, pady=10, relief=GROOVE)
frame3.grid(row=2, column=0)


canvas_11 = Canvas(frame1, bg="lime", width=100, height=100)
canvas_11.grid(row=0, column=0, fill=None, padx=10, pady=10)
canvas_12 = Canvas(frame1, bg="orange", width=150, height=100)
canvas_12.grid(row=0, column=1, fill=None, padx=10, pady=10)
canvas_13 = Canvas(frame1, bg="grey", width=100, height=100)
canvas_13.grid(row=1, column=1, fill=None, padx=10, pady=10)


canvas_21 = Canvas(frame2, bg="magenta", width=200, height=50)
canvas_21.grid(row=0, column=0, fill=None, padx=10, pady=10)
canvas_22 = Canvas(frame2, bg="brown", width=200, height=50)
canvas_22.grid(row=0, column=1, fill=None, padx=10, pady=10)
canvas_23 = Canvas(frame2, bg="sky blue", width=200, height=50)
canvas_23.grid(row=1, column=0, fill=None, padx=10, pady=10)

canvas_31 = Canvas(frame3, bg="light green", width=400, height=50)
canvas_31.grid(row=0, column=0, fill=None, padx=10, pady=10)
window.mainloop()

 

위젯 배치 layout

- 압축 배치 pack() : pack(fill=BOTH)  # fill= X, Y, BOTH  

- 격자 배치 grid() : grid(row=2, column=1)

- 절대 위치 배치 place() : place(x=200, y=200)

 

 

 

3. 압축 배치 연습

 

from tkinter import *

window =Tk()
window.title("testing pack layout")
window.geometry("400x300+100+200")



label1 = Label(window, text="label 1", bg="red", fg="white").pack(fill=X, padx=10, pady=10)
label2 = Label(window, text="label 2", bg="green", fg="black").pack(fill=X, padx=10, pady=10)
label3 = Label(window, text="label 3", bg="yellow", fg="white").pack(fill=X, padx=10, pady=10)

label4 = Label(window, text="label 4", bg="red", fg="black").pack(fill=X,padx=10, pady=10, side=LEFT)
label5 = Label(window, text="label 5", bg="green", fg="black").pack(fill=X, padx=10, pady=10, side=LEFT)
label6 = Label(window, text="label 6", bg="blue", fg="black").pack(fill=X, padx=10, pady=10, side=LEFT)

listbox = Listbox(window)
listbox.pack(fill=BOTH, expand=1)
L = [100, 200, 300, 400, 500]
for i in range(len(L)):
    listbox.insert(END, str(L[i]))

mainloop()

 

 

grid 함수

- column = 열, row = 행

- columnspan = 위젯이 차지하는 열 칸 수, rowspan = 위젯이 차지할 행칸 수

- in : 위젯이 놓일 위젯, 디폴트는 부모 위젯

- sticky : 위젯을 어떻게 붙일건지 디폴트는 중앙, NSEW는 셀 경계 딱붙인다.

 

entry 위젯 주요 함수

- focus() : 키보드 입력 가능하게 함

- bind() : 특정 이벤트시 실행 함수 바인드

 

 

 

 

4. 그리드 레이아웃과 엔트리 바인드

- window.bind()와 Button(command=())로 엔터키를 누르거나("<Return>"), 버튼누를시 fetch()함수 호출

 -> 엔터누르거나 fetch 버튼 클릭 시 fetch 함수대로 입력 데이터가 잘 출력된다.

from tkinter import *

def fetch(cells):
    print("- input data -")
    for i, e in enumerate(cells):
        print("  {0}:{1}".format(fields[i], e.get()))

def make_form(fields):
    cells = []
    for r, field in enumerate(fields):
        label = Label(window, width=10, text= field)
        entry = Entry(window)
        label.grid(row=r, column=0, sticky=NSEW)
        entry.grid(row=r, column=1, sticky=NSEW)
        cells.append(entry)
    return cells

if __name__ == "__main__":
    window = Tk()
    window.title("Input Dialog with label and entry")
    fields = ("Name", "Age", "Address")
    cells = make_form(fields)
    window.bind("<Return>", (lambda event, e=cells: fetch(e)))
    #엔터키 눌릴떼 람다식 호출 바인드
    #cells를 e에 담고 fetch 호출
    # 주의 : bind 함수 호출시 lambda 식 앞단에 인수를 2개해야한다.
    Button(window, text="Fetch", bg="green",
           command=(lambda e=cells:fetch(e))).grid(row=3, column=0, sticky=NSEW)
    # 버튼 눌릴때도 fetch(e) 호
    Button(window, text="Quit", bg="Red", command=window.destroy).grid(row=3, column=1, sticky=NSEW)
    print("grid size : ", window.grid_size())
    window.grid_columnconfigure(1, weight=1)
    window.grid_rowconfigure(0, weight=1)
    window.mainloop()

 

 

캔버스 객체의 함수들

- after(delay_ms, callback=None, *args) : 딜레이 타임 후 콜백함수 호출

- bind(sequence=None, func=None, add=None)  : 시퀀스 이벤트에 func 바인딩

- bind_all(csequence=None, func=None, add=None) : 모든 위젯에 func 바인딩

- bind_class(className, sequence=None, func=None, addd=None) : 해당 클래스 모든 위젯에 이벤트 func 바인딩

- create_image/line/oval/polygon/rectangle/text/window

- pos = canvas.coords(객체이름, pos) : 해당 객체 위치

- destroy() : 위젯과 객체제거

- mainloop() : 반복 시작

- quit() 반복 중지

- move(item, dx, dy) : 해당 아이템 객체를 이동

- update() 디스플레이 갱신

 

 

 

Event

- 버튼 : <Button-1>(마우스 왼쪽버튼 클릭), <Button-2> (마우스 휠 클릭), <button-3> (마우스 우클릭)

- 모션 : <Motion>(마우스 움직일때), <B1-Motion> 마우스 좌클릭채 움직일때, ...

- 위젯 동작 : <Configure> 위젯 모양 변경시, <Enter> 위젯안으로 마우스 들어갈때, <Leave> 위젯에서 나올때

- etc ...

 

 

 

 

5. 프레임, 캔버스 크기변경 이벤트 시 함수 호출

- 모든 위젯 크기 변경시 onsize 호출

- 그 중 위젯이 프레임일때 현재 크기반영해 라벨 변경

from tkinter import *

def onSize(event):
    if event.widget == frame: # 이벤트 호출된 위젯이 프레임인경우
        frame.update() # 라벨 변경전 갱신
        label_fr.configure(text="frame size: {}x{}".format(frame.winfo_width(), frame.winfo_height()))
        canvas.update()
        label_cnv.configure(text="canvas size: {}x{}".format(canvas.winfo_width(), canvas.winfo_height()))
    
    
if __name__ == "__main__":
    global label_Fr, label_cnv, frame, canvas
    window =Tk()
    window.title("finding frame and canvas size at resizing events")
    frame = Frame(window, bg="light green", bd=10, padx=50, pady=50, relief=GROOVE)
    frame.pack(expand=YES, fill=BOTH)
    canvas = Canvas(frame, bg="white", width=600, height=400)
    canvas.pack(expand=YES, fill=BOTH, padx=10, pady=10) #frame, canvas 양방향 조절 가능
    frame.update()
    label_fr = Label(canvas, text="frame size: {} x {}".format(frame.winfo_width(), frame.winfo_height()))
    label_fr.grid(row=0, column=0, sticky=N)
    canvas.update()
    label_cnv = Label(canvas, text="canvas size: {} x {}".format(canvas.winfo_width(), canvas.winfo_height()))
    label_cnv.grid(row=1, column=0, sticky=S)
    
    # <Configure> : 위젯모양변경시 이벤트 -> onSize() 호출
    # bind_all(컨피겨, func) -> 모든 위젯 크게 변경시 onsize() 호출 
    window.bind_all("<Configure>", onSize)
    window.mainloop()

 

 

 

 

+ 깃 로컬 저장소를 원격 저장소에 올리기

1. git init으로 깃 저장소 초기화

2. git add . 모든 파일 스태징

3. 커밋

 

4. git remote add origint 원격저장소 주소

5. git remote -v로 연결되었는지 확인

6. git push -u origit master 로컬 저장소 브랜치를 원격 저장소 master로 푸시(u는 지역과 원격 연결을 위해 한번만)

 

 

7. 깃헙에 잘올라갔다.

+ Recent posts