본문 바로가기
프로그래밍/파이썬

[파이썬 GUI] tkinter 3(위젯을 화면에 배치하는 방법, pack, grid, place)

by 인성패밀리 2022. 10. 14.
반응형

tkinter에서 위젯을 나타내게 할 때 사용되는 3가지 메소드가 있습니다.

 

1. pack method

2. grid method

3. place method

 

1번 pack method는 절대적인 위치에 등장시키고 싶을 때 사용합니다. 예를 들어 300x400, 또는 이와 다른 화면 크기에서 위젯을 맨 위, 맨 아래 등에 배치하고 싶을 때는 pack method를 사용합니다. 이 메소드는 내가 어디에 정확하게 배치하고 싶을 때는 부정확할 가능성이 있습니다.

 

2번 grid method는 엑셀과 같다고 생각하면 됩니다. 엑셀과 같이 격자를 위젯의 크기에 맞게 자동으로 설정이 됩니다. 자동으로 격자가 생성되기 때문에 위젯의 크기가 들쭉 날쭉한다면 사용하기 곤란할 수도 있습니다.

 

3번 place는 좌표를 이용하여 위젯을 정확히 배치할 수 있습니다. 내가 어디에 배치하고 싶은 좌표를 찍으면 되기 때문이죠. 그러나 이 방법은 가장 정확히 배치하면서도 까다로울 수 있는 방법입니다. 그러나 저는 place를 사용하는 것이 가장 속이 편안했습니다. 이유는 어찌 되었건 내가 원하는 위치에 배치할 수 있기 때문이였습니다.

 

이제부터는 코드와 함께 알아보겠습니다.

먼저 pack method입니다.

from tkinter import *


root = Tk()
root.geometry("300x300+300+300")

Label(root, text="string").pack()

text2 = Label(root, text="python")
text2.pack()

root.mainloop()

Label(root, text="string").pack()

-> 지난 번에 올렸던 글에서 보던 형태입니다. Label(root, text="string") 부분은 Label 위젯을 생성한 것이고 뒤에 .pack()는 위젯을 등장시킨 것입니다.

pack method의 괄호 안에 아무것도 없으면 디폴트로 화면의 맨 위 중앙에 나타나게 됩니다.

 

text2 = Label(root, text="python")

-> 변수에 위젯을 담은 것입니다. 이런 식으로 사용한다면 위젯의 속성을 변경할 수 있습니다. 위젯의 속성을 변경할 일이 있다면 반드시 변수를 사용해야합니다.

 

text2.pack()

-> 위젯을 담은 변수에 pack()를 사용했으니 해당 위젯이 등장할 것입니다. 역시나 괄호 안에 아무것도 없으므로 디폴트로 화면 위 중앙에 나타나게 됩니다. 그러나 먼저 등장시킨 string과 겹치는 것이 아니라 그 아래에 나오게 됩니다.

 

코드 실행 결과입니다.

코드 실행 결과

 

이제 pack methon에서 사용할 수 있는 옵션들을 알아보겠습니다.

from tkinter import *

root = Tk()
root.geometry("400x300+300+300")
root.title("test")

label1 = Label(root, text="Tkinter", fg="yellow", font=('굴림', 30, 'bold'))
label1.pack(fill='x',
            padx=5,
            pady=5,
            ipadx=5,
            ipady=5,
            side='top',
            anchor='e')

print(label1.pack_info())

root.mainloop()

이 코드의 실행 결과입니다.

 

fill='x'

-> 현재 위치에서 모든 x축이 해당 위젯의 영역이 됩니다.

-> y를 사용하면 현재 위치의 모든 y축이 위젯의 영역이 됩니다.

-> both를 사용하면 x축과 y축 모두 위젯의 영역이 됩니다.

-> LabelFrame을 사용할 때 유용합니다.

-> 문자열로 된 값이 필요합니다.

 

padx=5, pady=5

-> html을 해보셧다면 padding의 개념이 있는데 이와 동일합니다. padx는 x방향의 위젯의 외부 간격을 말합니다. pady는 y축 방향의 위젯의 외부 간격을 말합니다.

-> 위젯이 만약 다닥다닥 붙어있을 때 pad 속성을 사용하면 일정 간격 떨어트릴 수 있습니다.

 

ipadx=5, ipady=5

-> padx, pady가 외부 간격이였다면 ipadx, ipady는 내부 간격입니다. 

-> pad와 ipad모두 양의 정수 값이 사용됩니다.

pad와 ipad에 대해서는 그림으로 이해하면 편리합니다.

위젯의 크기 그림

side='top'

-> 특정 위치로 위젯을 보낼 수 있습니다. 문자열 값이 사용되며, 보낼 수 있는 위치는 top, bottom, left, right만 가능합니다.

 

anchor='e'

-> 이 속성 역시 특정 위치로 위젯을 보낼 수 있습니다. 문자열 값이 사용되며, 보낼 수 있는 위치는 동서남북, 북동, 북서, 남동, 남서, center가 있습니다. 디폴트 값은 center입니다. 동서남북을 간단하게 n, s, w, e, ne, nw, sw, se로 사용합니다.

 

그런데 코드의 실행 결과를 보면 무언가 이상합니다. 분명 anchor 속성으로 e(동쪽)를 부여했는데 위젯은 정 가운데 위치하고 있습니다. 바로 fill 속성으로 x축을 모두 해당 위젯에게 주었기 때문에 동쪽으로 이동을 하나 마나 정 가운데 위치 한 것으로 보입니다. 만약 fill 속성의 기본 값은 none을 부여했다면 결과가 다르게 나올 것 입니다.

fill = 'none'을 한 결과

 

여기까지가 보통 사용하는 pack method의 옵션들입니다. 저는 프레임을 배치할 때를 제외하고는 보통 사용하지 않습니다.

또한 주의할 점이 있는데 pack은 grid와 혼용해서 사용이 불가하다는 점입니다. 이 말은 어떤 위젯은 pack를 사용하고 또 다른 위젯은 gird를 사용하고 이 방식이 안된다는 의미입니다. 단, place와는 혼용이 가능합니다.

이번에는 grid를 사용하는 방식을 알아보겠습니다.

from tkinter import *

root = Tk()
root.geometry("400x300+300+300")

text1 = Label(root, text="string")
text1.grid(row=0, column=0)

text2 = Label(root, text="coding")
text2.grid(row=0, column=1)

text3 = Label(root, text="python")
text3.grid(row=1, column=0)

root.mainloop()

text1.grid(row=0, column=0)

-> grid method의 필수 속성입니다. row는 가로 줄 번호, column은 세로 줄 번호 입니다.

-> 시작부터 row=100, column=100이라고 해도 원하는 대로 되지 않을 것입니다. 그 이유는 grid가 자동으로 격자를 생성하기 때문입니다.

-> 편안하게 인덱스 번호를 세는 것 처럼 0부터 차곡차곡 넣으면 마음이 편안해집니다.

 

이 코드를 사용한 결과입니다.

코드 실행 결과

아무 옵션을 넣지 않고 디폴트로 사용한 경우인데 아까 위젯의 크기에 따라 자동으로 격자를 생성한다 하였습니다. 때문에 python이라는 글자가 string보다 길어서 python의 크기에 맞게 가로 간격이 변화되었습니다.

 

grid의 옵션에 대해서 알아보겠습니다.

from tkinter import *

gui = Tk()
gui.geometry("400x300+300+300")
gui.title("grid 사용하기")

t_list = []
for i in range(1, 10):
    tmp = Button(gui, text=f"t{i}")
    t_list.append(tmp)

t_list[0].grid(row=0, column=0, padx=5, pady=5, ipadx=5, ipady=5, rowspan=2)
t_list[1].grid(row=0, column=1, padx=5, pady=5, ipadx=5, ipady=5, columnspan=2)
t_list[2].grid(row=1, column=1, padx=5, pady=5, ipadx=5, ipady=5)
t_list[3].grid(row=2, column=0, padx=5, pady=5, ipadx=5, ipady=5, columnspan=2)
t_list[4].grid(row=1, column=2, padx=5, pady=5, ipadx=5, ipady=5, rowspan=2)

t_list[0]["height"] = 4
t_list[1]["width"] = 8
t_list[3]["width"] = 8
t_list[4]["height"] = 4

gui.mainloop()

이제까지 Label을 사용했었는데 Label로는 grid의 옵션을 표현하기 힘들어서 button을 사용해보았습니다. 우리가 알아볼 것은 grid라서 신경쓰지 않아도 됩니다. 

 

이 코드의 실행 결과입니다.

html의 tr td 태그 속성 공부할 때도 보았던 기억이 납니다.

t_list[1].grid(row=0, column=1, padx=5, pady=5, ipadx=5, ipady=5, columnspan=2)

-> row와 column은 방금 설명을 했었고, pad와 ipad는 pack method 설명할 때 했던 것과 동일합니다.

-> 코드에 보면 columnspan과 rowspan 속성이 있는데 html에서 table 태그 사용할 때 연습해보았던 것과 동일한 의미입니다. columnspan은 세로 줄을 몇 칸 통합할 것인지 rowspan은 가로 줄을 몇 칸 통합할 것인지 정하는 것입니다.

-> 이 부분은 직접 값을 변경해보면서 테스트 하시면 훨씬 이해가 빠릅니다.

 

예제에는 없지만 간혹 사용할 수 있는 속성이 있습니다.

sticky = 'n'

-> 동서남북, 북동, 북서, 남동, 남서를 문자열 형태의 영어 약자를 사용하면 됩니다. 

-> 이 속성을 사용하면 위젯이 들어간 칸에서 동서남북 등으로 움직일 수 있습니다.

 

grid는 일정한 간격(격자)으로 위젯을 배치하는 것이여서 pack처럼 위치를 절대적으로 지정하는 것이 아니라 내가 원하는 칸에 넣는 method입니다. 단 주의할 점은 위젯의 크기가 일정한 편이면 편리하게 사용할 수 있으나 과도하게 들쭉 날쭉하다면 원하는 대로 모양은 나오지 않을 것입니다.

마지막으로 place method입니다.

사실 상 제일 속 편한 방법입니다. 그냥 좌표만 찍어주면 됩니다.

from tkinter import *

root = Tk()
root.geometry("400x300+300+300")

text1 = Label(root, text="string")
text1.place(x=30, y=30)

text2 = Label(root, text="coding")
text2.place(x=100, y=100)

root.mainloop()

이 코드의 실행 결과입니다.

정말 단순합니다. 좌표만 잘 사용하면 원하는 위치에 딱딱 넣을 수 있습니다.

딱히 설명 안해도 충분히 아실것이라 생각이 됩니다.

 

place에서 사용할 수 있는 옵션입니다.

from tkinter import *

gui = Tk()
gui.geometry("400x300+300+300")

tmp = Label(gui, text="string", borderwidth=3, relief="solid")
tmp.place(x=200, y=100, width=100, height=150)

gui.mainloop()

place는 위젯의 크기를 조정할 수도 있습니다. width, height 속성을 이용하면 조정할 수 있습니다. 이 코드를 실행하면 직사각형이 보이는데 위젯의 크기를 조정하는 것이지 글자를 키우는 것이 아닙니다.

 

여기까지 위젯을 등장시키는 방법을 알아보았습니다. 긴 글 읽어주셔서 감사드리며 헷갈리는 부분이 있다면 댓글로 남겨주시면 감사드리겠습니다.

반응형

댓글