Учебник Tkinter - управление макетами

  1. Tkinter pack, grid и lace - метод раскладки
  2. Tkinter grid Метод раскладки
  3. Метод Tkinter place Метод

В предыдущих разделах мы представили несколько типов виджетов Tkinter, таких как label, button, выпадающее меню и др. Между тем, мы также вкратце рассказали о том, как раскладывать эти виджеты в окне программы. Это ключевой момент, который вы узнаете в этом разделе - методы управления геометрией Tkinter.

В Tkinter есть три метода управления геометрией, то есть пакет, сетка и место. Давайте рассмотрим их один за другим.

Tkinter pack, grid и lace - метод раскладки

Метод pack, как буквально указано, упаковывает виджет в оконную рамку после его создания. Мы столкнулись с этим методом компоновки в разделе Tkinter Label, где также перечислены все опции pack.

Мы покажем, как компоновать виджеты методом pack (также его опции). Несколько примеров помогут продемонстрировать правильную конфигурацию.

Tkinter pack Layout - Relative Position

Tkinter Geometry_Pack_Relative Position.py
import tkinter as tk    
    
app = tk.Tk()
app.geometry('300x200')

buttonW = tk.Button(app, text="West", width=15)
buttonW.pack(side='left')

buttonE = tk.Button(app, text="East", width=15)
buttonE.pack(side='right')

app.mainloop()

Запустите программу, у вас появится такое окно,

Метод компоновки Tkinter-пакета - относительное положение со стороны

Как видно, buttonWest щёлкает на левой стороне окна, а buttonEast щёлкает на правой стороне. Вы можете попробовать масштабировать размер окна внизу, но вы увидите, что они все равно будут цепляться за боковые стороны окна и относительное положение не изменится.

buttonW.pack(side='left')

У side есть четыре варианта -

  1. top
  2. bottom
  3. left
  4. right

Он помещает виджет на side окна. Как показано в примере, buttonW расположена с левой стороны окна, потому что side='left', в то время как buttonE расположена с правой стороны окна, потому что side='right'.

Теперь у нас есть интересный сценарий, что произойдет, если два виджета будут иметь одно и то же свойство side, как будет раскладка?

Попробуйте ответить сами или проверьте, запустив следующие коды.

Tkinter Geometry_Pack_Relative Position Two side.py
import tkinter as tk
    
    
app = tk.Tk()
app.geometry('300x200')

buttonW = tk.Button(app, text="West", width=15)
buttonW.pack(side='left')

buttonE1 = tk.Button(app, text="East 1", width=15)
buttonE1.pack(side='right')

buttonE2 = tk.Button(app, text="East 2", width=15)
buttonE2.pack(side='right')

app.mainloop()

Tkinter pack для добавления внутренней и внешней подкладки виджета

В некоторых случаях необходимо добавить подкладку внутри или снаружи виджета, чтобы было меньше заторов между виджетами, а также между текстом виджета и границами виджета. Теперь Вам нужны такие опции, как padx, pady, ipadx и ipady.

Tkinter Geometry_Pack_Padding.py
import tkinter as tk
    
app = tk.Tk()
app.geometry('300x200')

buttonW = tk.Button(app, text="West")
buttonW.pack(side='left', ipadx=20, padx=30)

buttonE = tk.Button(app, text="East")
buttonE.pack(side='right', ipadx=20, padx=30)

app.mainloop()

Метод компоновки виджетных пакетов - увеличьте подкладку виджета

Обе кнопки добавляют внутренние 20 единиц набивки и внешние 30 единиц в x, при этом единица измерения является пиксельной, но не шириной одного символа.

Tkinter pack Макет Заполнение в направлении х, у

Следующая реализация кода может автоматически заполнить размер виджета той же шириной или той же высотой, что и окно, а при увеличении окна размер элемента управления может автоматически изменяться вместе с размером окна.

Tkinter Geometry_Pack_Fill.py
import tkinter as tk
    
app = tk.Tk()
app.geometry('300x200')

buttonX = tk.Button(app, text="Fill X", bg="red", height=5)
buttonX.pack(fill='x')

buttonY = tk.Button(app, text="Fill Y", bg="green", width=10)
buttonY.pack(side='left', fill='y')

app.mainloop()

Метод заполнения X,Y Направление в кинтер-пакете

butonX.pack(fill='x') означает, что buttonX заполнит ширину всего окна. Аналогично, fill='y' заполнит высоту всего окна, а тем временем fill='both' заполнит и ширину, и высоту.

Tkinter pack Вариант раскладки expand - автоматически развернется

Выше опция fill= автоматически заполнит виджет в направлении x и/или y при изменении размера окна. Другое похожее требование - как автоматически отобразить все содержимое, если виджет включает в себя несколько опций, например, список?

Tkinter Geometry_Pack_Expand.py
import tkinter as tk
import calendar    
    
app = tk.Tk()

buttonX = tk.Button(app, text="Label ", bg="blue", height=5)
buttonX.pack(fill='x')

listboxA = tk.Listbox(app, width=10)
listboxA.pack(fill='both', expand=1)

for i in range(1,13):
    listboxA.insert(tk.END, calendar.month_name[i])
    
app.mainloop()

Метод компоновки ткинтер-пакета позволяет включить опцию разворачивания

Когда expand=True или expand=1, в окне списка будут перечислены все элементы, от Января до Декабря, как показано в вышеприведенном примере.

Если expand установлен как False, то по умолчанию в поле списка будут показаны только первые 10 элементов. Вам нужно использовать мышь или клавиши направлений, чтобы показать скрытые элементы после того, как поле списка выбрано.

listboxA.pack(fill='both', expand=0)

expand=0 отключает поле списка для автоматического показа всех элементов.

Метод раскладки кинтер-пакетов при отключенной опции расширения

Tkinter grid Метод раскладки

Tkinter grid - это еще один, а также самый важный метод геометрии макета. Этому методу следует научиться, если вы хотите изучить только один единственный метод среди всех менеджеров по геометрии.

grid часто используется в диалоговых окнах, и вы можете разместить виджеты, основываясь на координатах положения сетки. Метод компоновки grid может иметь стабильные относительные позиции всех виджетов.

Следующий пример создаст относительно сложный GUI по сравнению с вышеприведенными примерами, который использует как можно больше опций grid, которые будут объяснены в следующих разделах.

Tkinter Geometry_Grid_Basic.py
import tkinter as tk

app = tk.Tk() 

labelWidth = tk.Label(app,
                    text = "Width Ratio")
labelWidth.grid(column=0, row=0, ipadx=5, pady=5, sticky=tk.W+tk.N)

labelHeight = tk.Label(app,
                    text = "Height Ratio")
labelHeight.grid(column=0, row=1, ipadx=5, pady=5, sticky=tk.W+tk.S)


entryWidth = tk.Entry(app, width=20)
entryHeight = tk.Entry(app, width=20)

entryWidth.grid(column=1, row=0, padx=10, pady=5, sticky=tk.N)
entryHeight.grid(column=1, row=1, padx=10, pady=5, sticky=tk.S)


resultButton = tk.Button(app, text = 'Get Result')
resultButton.grid(column=0, row=2, pady=10, sticky=tk.W)

logo = tk.PhotoImage(file='python.gif')
labelLogo = tk.Label(app, image=logo)

labelLogo.grid(row=0, column=2, columnspan=2, rowspan=2,
               sticky=tk.W+tk.E+tk.N+tk.S, padx=5, pady=5)

app.mainloop()

Метод компоновки сетки

Tkinter grid column и row опции

labelWidth.grid(column=0, row=0, ipadx=5, pady=5, sticky=tk.W+tk.N)

Каждый виджет должен быть помещен в абсолютную ячейку методом компоновки grid. Координаты ячеек определяются column и row.

Виджет labelWidth помещается в ячейку позиции (0, 0). Координата начинается с верхнего левого угла окна.

Варианты ipadx, ipady, padx и pady такие же, как и в методе pack.

Опция Tkinter grid sticky

sticky определяет, как виджет прилипает к ячейке, когда виджет меньше ячейки.

sticky Значение
W держаться левее
E держаться правой руки
N держаться сверху
S держаться дна

Опция по умолчанию sticky является центральной, т.е. W+E+N+S.

Опции Tkinter columnspan и rowspan

labelLogo.grid(row=0, column=2, columnspan=2, rowspan=2,
               sticky=tk.W+tk.E+tk.N+tk.S, padx=5, pady=5)

Координата ячейки labelLogo - (column=2, row=0) и размер логотипа относительно велик, поэтому он соотносится с размером ячейки 2x2. columnspan=2 и rowspan=2 означает, что виджет имеет развороты двух ячеек как в направлении X, так и в направлении Y, начиная с положения виджета.

Метод Tkinter place Метод

Метод Tkinter place помещает виджет в абсолютное или относительное положение в окне. Мы по-прежнему используем тот же подход, что и выше для введения опций этого метода компоновки.

Tkinter Geometry_Place_Basic.py
import tkinter as tk

app = tk.Tk()
app.geometry('300x300') 

labelA = tk.Label(app, text = "Label (0, 0)", fg="blue", bg="#FF0")
labelB = tk.Label(app, text = "Label (20, 20)", fg="green", bg="#300")
labelC = tk.Label(app, text = "Label (40, 50)", fg="black", bg="#f03")
labelD = tk.Label(app, text = "Label (0.5, 0.5)", fg="orange", bg="#0ff")

labelA.place(x=0, y=0)
labelB.place(x=20, y=20)
labelC.place(x=40, y=50)
labelD.place(relx=0.5, rely=0.5)

app.mainloop()

Метод Tkinter Place Layout

Tkinter place Абсолютная позиция

labelA.place(x=0, y=0)
labelB.place(x=20, y=20)

Опции x= и y= в place определяют абсолютные позиции виджета, которые имеют единицу измерения в виде пикселя. Например, lableB.place(x=20, y=20) означает, что labelB помещается в координату (20, 20).

Tkinter place относительное положение

Недостатком абсолютной позиции является то, что если в окне размещены другие виджеты с относительными позициями, то при масштабировании окна виджет, использующий абсолютное расположение позиций, возможно, будет иметь перекрытие с другими виджетами.

Метод place также имеет опцию относительной позиции, то есть,

labelD.place(relx=0.5, rely=0.5)

Где relx и rely находятся в диапазоне 0.0~1.0. Это относительный процент положения виджета к размеру окна.

Например, relx=0.5, rely=0.5 означает, что виджет размещается в 50% от ширины окна и 50% от высоты окна.

relx=1.0 - правая граница окна, а rely=1.0 - нижняя граница окна.

comments powered by Disqus