Я написал графический интерфейс на Tkinter с множеством виджетов. Графический интерфейс работает, но из-за такого количества переменных он довольно запутан. Поэтому я подумал и исследовал, не проще ли поместить подкадры в подклассы.
В принципе мой графический интерфейс устроен следующим образом:

Похожий вопрос задан здесь (Ссылка), но ответы больше направлены на структурирование графического интерфейса с помощью виджетов, а не sections. Вот почему я не уверен, что нахожусь на правильном пути. Я протестировал его с помощью следующего кода, но уже столкнулся с загадочными проблемами:
import tkinter as tk
from tkinter import ttk
class main_window(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Adding a title to the window
#self.wm_title("LiL-SimReg")
self.geometry("800x1000")
self.title(" xxx ")
INPUTframe(self)
class INPUTframe(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
tk.Frame(self, width=800, height=150).place(x=0,y=0)
label10 = tk.Label(self, text = "xxx", font=('Arial',12)).place(x=10,y=0)
label1 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=30, y=30)
button1 = tk.Button(self, text='xxx').place(x=100,y=30)#,command = lambda: path(1))
textentry1=tk.StringVar()
entry1 = tk.Entry (self, textvariable=textentry1).place(x=160,y=30,width = "350")
label11 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=500,y=30)
label2 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=30,y=60)
button2 = tk.Button(self, text='xxx').place(x=100,y=60)#,command = lambda: path(2))
textentry2=tk.StringVar()
entry2 = tk.Entry (self, textvariable=textentry2).place(x=160,y=63,width = "350")
label21 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=500,y=60)
textentry21=tk.DoubleVar(value='x')
entry21 = tk.Entry (self, textvariable=textentry21).place(x=580,y=63,width = "30")
label3 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=30,y=90)
button3 = tk.Button(self, text='xxx').place(x=100,y=90)#,command = lambda: path(3))
textentry3=tk.StringVar()
entry3 = tk.Entry (self, textvariable=textentry3).place(x=160,y=93,width = "350")
label31 = tk.Label(self, text = "xxx", font=('Arial',10)).place(x=500,y=90)
textentry31=tk.DoubleVar(value='x')
entry31 = tk.Entry (self, textvariable=textentry31).place(x=580,y=93,width = "30")
if __name__ == "__main__":
testObj = main_window()
testObj.mainloop()
Если я использую .place для виджетов, это иногда работает. Лучше это работает с .pack, но тоже не всегда, поэтому кажется, что мой подход неправильный. Ошибки нет, просто ее нет или виджеты отображаются случайным образом.
Не могли бы вы дать мне совет, имеет ли этот подход смысл и в чем ошибка в моем коде?
Привет @TheLizzard, с помощью этой команды я хочу разместить INPUTFRAME.
Используйте self.place(...).
@acw1668 acw1668 Я уже пробовал self.place(), но он работает не так, как ожидалось. Куда именно мне нужно это поставить?
@ Брайан Окли Я нахожу твое имя во многих вопросах по этому поводу. Знаете, почему это не так хорошо работает с местом?
Добавьте текст к изображению структуры графического интерфейса, неясно, где должна располагаться каждая метка/запись/кнопка. Я не знаю, как это должно выглядеть.
Используйте self.place(...), чтобы заменить строку tk.Frame(...).place(...).






Чтобы позиционировать INPUTframe, вам необходимо обновить его __init__.
class INPUTframe(tk.Frame):
def __init__(self, parent, width=800, height=150):
tk.Frame.__init__(self, parent, width=width, height=height)
self.place(x=0, y=0)
label10 = tk.Label(self, text = "xxx", font=('Arial',12)).place(x=10,y=0)
...
Вы также можете структурировать свое приложение, как в этом примере (один класс).
Если вы хотите разместить фрейм внутри функции __init__(), вам не следует вызывать:
tk.Frame(self, width=800, height=150).place(x=0,y=0)
потому что вместо этого будет создан другой кадр.
Вместо этого используйте self.place(x=0, y=0, width=800, height=150).
Однако я бы посоветовал не вызывать функцию макета самим виджетом. Вместо этого родитель несет ответственность за размещение своих дочерних элементов:
...
class main_window(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Adding a title to the window
#self.wm_title("LiL-SimReg")
self.geometry("800x1000")
self.title(" xxx ")
frame = INPUTframe(self, width=800, height=150)
frame.place(x=0, y=0)
class INPUTframe(tk.Frame):
def __init__(self, parent, **kwargs):
tk.Frame.__init__(self, parent, **kwargs)
label10 = tk.Label(self, text = "xxx", font=('Arial',12)).place(x=10,y=0)
...
Так выглядит графический интерфейс?
Я использую Python 3.12.5. Если нет, то игнорируйте ваш parent.
Я изменился (self,...)
на (parent, ...) для каждого виджета
В строке 20, label10 = tk.Label(parent, text = "xxx", bg='red', font=('Arial',12)).place(x=30,y=10) #<== change layout.
Скриншот:
большое спасибо. Это работает! Знаете ли вы, почему .place() не сработал? Это функция или это ошибка наследования, которую я допустил? С помощью .grid() и .place() мне удалось заставить его работать, но мне пришлось менять весь макет, поскольку до сих пор я в основном работал с .place().
Рад, что смог помочь.
Макет Place() выполняет вашу работу. Есть так много способов сделать это.
Прежде всего, когда вы объявляете виджет как переменную, вы не можете добавлять к нему pack/place. вместо,
widget = Widget_type(parent_widget)
widget.pack() # or place
Также следует упомянуть функцию, которая запускается виджетом, следующим образом.
btn = Button(parent_widget, command = function_name) # or lambda function instead of function_name
btn.pack() # or place
Требуемого вами поведения можно легко добиться с помощью пакета. Я предположил, что метка1 и кнопка1 расположены слева, а запись1 и метка11 — справа. Этот комбинированный виджет расположен вторым сверху. (Как я понял из вашего рисунка). Мне не понравилось то место, которое вы разместили методом place.
import tkinter as tk
from tkinter import ttk
class main_window(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Adding a title to the window
#self.wm_title("LiL-SimReg")
self.geometry("800x1000")
self.title(" xxx ")
top_frame = tk.Frame(self)
top_frame.pack(side = 'top')
label10 = tk.Label(top_frame, text = "xxx", font=('Arial',12))
label10.pack(side = 'top')
second_top = tk.Frame(self)
second_top.pack(side = 'top', pady=20)
second_top_left = tk.Frame(second_top)
second_top_left.pack(side= 'left')
second_top_right = tk.Frame(second_top)
second_top_right.pack(side= 'right')
# assuming label1 & button1 on left side and entry1 and label11 on right side
label1 = tk.Label(second_top_left, text = "xxx", font=('Arial',10))
label1.pack(side= 'top')
button1 = tk.Button(second_top_left, text='xxx')
button1.pack(side = 'top')
textentry1=tk.StringVar()
entry1 = tk.Entry (second_top_right, textvariable=textentry1)
entry1.pack(side='top')
label11 = tk.Label(second_top_right, text = "xxx", font=('Arial',10))
label11.pack(side='top')
third_top = tk.Frame(self)
third_top.pack(side='top', pady = 20)
label2 = tk.Label(third_top, text = "xxx", font=('Arial',10))
label2.pack(side = 'top')
button2 = tk.Button(third_top, text='xxx')
button2.pack(side = 'top')
textentry2=tk.StringVar()
entry2 = tk.Entry (third_top, textvariable=textentry2)
entry2.pack(side = 'top')
label21 = tk.Label(third_top, text = "xxx", font=('Arial',10))
label21.pack(side = 'top')
textentry21=tk.DoubleVar(value='x')
entry21 = tk.Entry (third_top, textvariable=textentry21)
entry21.pack(side = 'top')
bottom_frame = tk.Frame(self)
bottom_frame.pack(side= 'top', pady = 20)
label3 = tk.Label(bottom_frame, text = "xxx", font=('Arial',10))
label3.pack(side = 'top')
button3 = tk.Button(bottom_frame, text='xxx')
button3.pack(side = 'top')
textentry3=tk.StringVar()
entry3 = tk.Entry (bottom_frame, textvariable=textentry3)
entry3.pack(side = 'top')
label31 = tk.Label(bottom_frame, text = "xxx", font=('Arial',10))
label31.pack(side = 'top')
textentry31=tk.DoubleVar(value='x')
entry31 = tk.Entry (bottom_frame, textvariable=textentry31)
entry31.pack(side = 'top')
if __name__ == "__main__":
testObj = main_window()
testObj.mainloop()
Почему у тебя
tk.Frame(...).place(x=0,y=0)? Он создает рамку и размещает ее, не помещая внутрь никаких виджетов. Также обратите внимание на менеджер геометрииGrid, который может оказаться более полезным с учетом вашей диаграммы.