Вопрос-Ответ

Tkinter - Geometry management

Tkinter - Управление геометрией

Я вижу много вопросов к tkinter, которые довольно часто задают не об ошибках в их коде, а спрашивают, как мне организовать свой графический интерфейс. Итак, я хотел бы получить ответ, который сосредоточит внимание на этом и поможет новичкам немного сориентироваться.

Переведено автоматически
Ответ 1

Базовые знания об управлении геометрией tkinters

Управление геометрией в tkinter характеризуется этой цитатой здесь:


По умолчанию на экране отображается окно верхнего уровня в его естественном размере, который определяется внутренне его виджетами и менеджерами геометрии.



Верхние уровни

Ваш верхний уровень - это первый вопрос, на который вам следует ответить:


  • wm_geometry: размер, положение на вашем экране?

  • wm_minsize \ wm_maxsize существуют ли минимальные или максимальные ограничения?

  • wm_resizable имеет ли пользователь возможность изменять его размер?

  • wm_attributes существуют ли такие атрибуты, как самый верхний или полноэкранный режим?

  • pack_propagate \ grid_propagate игнорирует запрошенные ширину и высоту дочерних элементов.

Примечание: Вы можете пропустить этот вопрос и позволить процессу решить, что все-таки потребуется.


Упорядочивание дочерних элементов

Для упорядочивания ваших дочерних элементов у вас есть 3 варианта, каждый из которых разработан для удовлетворения конкретных потребностей:

Упаковщик:


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


-> Я использую pack, чтобы быстро расположить несколько виджетов рядом друг с другом в master.

Россыпь


The placer - это менеджер геометрии для Tk. Он обеспечивает простое фиксированное размещение окон, при котором вы указываете точный размер и расположение одного окна, называемого подчиненным, внутри другого окна, называемого ведущим. Placer также предоставляет размещение на резиновом листе, где вы указываете размер и расположение подчиненного устройства в терминах размеров ведущего устройства, так что подчиненное устройство изменяет размер и расположение в ответ на изменения размера ведущего устройства. Наконец, placer позволяет вам смешивать эти стили размещения так, чтобы, например, подчиненный элемент имел фиксированную ширину и высоту, но был центрирован внутри главного элемента.


-> Иногда я использую place для приложений на одном листе или для установки фонового изображения.

Сетка


Команда grid используется для взаимодействия с grid geometry manager, который упорядочивает виджеты по строкам и столбцам внутри другого окна, называемого geometry master (или главное окно).


-> Grid - лучший выбор для более сложных приложений, содержащих множество виджетов.

Итак, вопрос, на который вам нужно ответить здесь, прежде чем выбрать один из этих менеджеров, заключается в том, как мне наилучшим образом организовать свое приложение?

Примечание:


Предупреждение: Никогда не смешивайте grid и pack в одном главном окне. Tkinter с радостью проведет остаток вашей жизни, пытаясь согласовать решение, которое устраивало бы обоих менеджеров. Вместо ожидания завершите работу приложения и еще раз взгляните на свой код. Распространенной ошибкой является использование неправильного родительского элемента для некоторых виджетов.


-> You can create a nested layout, in each master(window/frame) you've freedom of choice


Most important features

Most important features of each manger can help to answer your question. Because you will need to know if the manager can do what you wanna do.

For pack I think it is:


  1. fill stretch the slave horizontally, vertically or both

  2. expand The slaves should be expanded to consume extra space in their master.

  3. side Specifies which side of the master the slave(s) will be packed against.

  4. anchor it specifies where to position each slave in its parcel.

For place it should be:


  1. relheight -relheight=1.0, -height=-2 makes the slave 2 pixels shorter than the master.

  2. relwidth -relwidth=1.0, -width=5 makes the slave 5 pixels wider than the master.

  3. relx -relx=0.5, -x=-2 positions the left edge of the slave 2 pixels to the left out of the center.

  4. rely -rely=0.5, -x=3 positions the top edge of the slave 3 pixels below the center of its master.

And for grid it should be:


  1. columnspan Insert the slave so that it occupies n columns in the grid.

  2. rowspan Insert the slave so that it occupies n rows in the grid.

  3. sticky this option may be used to position (or stretch) the slave within its cell.

  4. grid_remove the configuration options for that window are remembered

  5. grid_columnconfigure

  6. grid_rowconfigure

for the last two options I recommend this answer here.


Read the docs

A working exampel to play with can be found here:

enter image description here

import tkinter as tk

root=tk.Tk()

holderframe = tk.Frame(root,bg='red')
holderframe.pack()

display = tk.Frame(holderframe, width=600, height=25,bg='green')
display2 = tk.Frame(holderframe, width=300, height=145,bg='orange')
display3 = tk.Frame(holderframe, width=300, height=300,bg='black')
display4 = tk.Frame(holderframe, width=300, height=20,bg='yellow')
display5 = tk.Frame(holderframe, bg='purple')


##display_green
display.grid(column = 0, row = 0, columnspan=3)
display.pack_propagate(0) #when using pack inside of the display
#display.grid_propagate(0) #when using grid inside of the display

#left
b =tk.Button(display, width =10,text='b')
b1 =tk.Button(display, width =10,text='b1')

b.pack(side='left')
b1.pack(side='left')
#right
b2 =tk.Button(display, width =20,text='b2')
b2.pack(side='right')
#center
l = tk.Label(display, text ='My_Layout',bg='grey')
l.pack(fill='both',expand=1)

#the order by using pack can be important.
#you will notice if you swip right with center.


##display2_orange
display2.grid(column=0,row=1, sticky='n')
display2.grid_propagate(0)

#column0
lab = tk.Label(display2, text='test2')
lab1 = tk.Label(display2, text='test2')
lab2 = tk.Label(display2, text='test2')
lab3 = tk.Label(display2, text='test2')
lab4 = tk.Label(display2, text='test2')
lab5 = tk.Label(display2, text='test2')
lab6 = tk.Label(display2, text='test2')

lab.grid(column=0,row=0)
lab1.grid(column=0,row=1)
lab2.grid(column=0,row=2)
lab3.grid(column=0,row=3)
lab4.grid(column=0,row=4)
lab5.grid(column=0,row=5)
lab6.grid(column=0,row=6)

#column1
lab10 = tk.Label(display2, text='test2')
lab11 = tk.Label(display2, text='test2')
lab12 = tk.Label(display2, text='test2')
lab13 = tk.Label(display2, text='test2')
lab14 = tk.Label(display2, text='test2')
lab15 = tk.Label(display2, text='test2')
lab16 = tk.Label(display2, text='test2')

lab10.grid(column=2,row=0)
lab11.grid(column=2,row=1)
lab12.grid(column=2,row=2)
lab13.grid(column=2,row=3)
lab14.grid(column=2,row=4)
lab15.grid(column=2,row=5)
lab16.grid(column=2,row=6)

display2.grid_columnconfigure(1, weight=1)
#the empty column gets the space for left and right effect

##display3_black
display3.grid(column=1,row=1,sticky='nswe')
display3.grid_propagate(0)

##display4_yellow
display4.grid(column=0,row=1,sticky='s')
display4.grid_propagate(0)

lab20 = tk.Label(display4, bg='black')
lab21 = tk.Label(display4, bg='red')
lab22 = tk.Label(display4, bg='orange')
lab23 = tk.Label(display4, bg='grey')

lab20.grid(column=0,row=0,sticky='ew')
lab21.grid(column=1,row=0,stick='e')
lab22.grid(column=2,row=0,sticky='e')
lab23.grid(column=3,row=0,stick='ew')

display4.grid_columnconfigure(0, weight=4)
display4.grid_columnconfigure(1, weight=2)
display4.grid_columnconfigure(2, weight=2)
display4.grid_columnconfigure(3, weight=1)

##display5_purple
display5.place(x=0,y=170,relwidth=0.5,height=20)
display5.grid_propagate(0)


root.mainloop()
2023-10-13 15:45 python tkinter