我正在尝试使用Tkinter在Python中构建GUI。我的想法是在根框架内构建几个框架。我可以出现2帧,但第三帧覆盖第二帧。我已经尝试将pack()和grid()作为根帧中的布局管理器。
我希望有一个“顶部的东西”框架和一个“底部的东西”框架,其间有1个Cat1框架和1到8个Cat2框架。当应用程序发现它控制的Cat2小部件数量时,GUI需要能够动态重建。
(另一个小问题。由于我介绍了Cat2Frame类并将tkFont变量移动到全局范围,我的12点字体仍然只有9分。)
这是我的清理过的代码段。 (尚未进入底部框架。)
def anchor(widget, rows=0, cols=0):
"""Takes care of anchoring/stretching widgets via grid 'sticky'"""
for r in range(rows):
widget.rowconfigure(r, weight=1)
for c in range(cols):
widget.columnconfigure(c, weight=1)
font_ = None
bold_ = None
bold_12 = None
class TkinterGui():
"""Tkinter implementation of the GUI"""
def __init__(self):
"""Create the Tkinter GUI"""
self._top_level = None
self._top_row = None
self._buildGui(_TITLE)
def _buildGui(self, title):
"""Build the Tkinter GUI"""
self._top_level = Tkinter.Tk()
font_ = tkFont.Font(family='FreeSans', size=9)
bold_ = tkFont.Font(family='FreeSans', size=9, weight='bold')
bold_12 = tkFont.Font(family='FreeSans', size=12, weight='bold')
anchor(self._top_level, 4, 1)
self._top_row = 0
self._buildTop()
self._top_row = 1
self._buildCat1()
t1 = Cat2Frame(self._top_level, "Cat2 1")
self._top_row = 2
t1.place_frame(self._top_row)
t5 = Cat2Frame(self._top_level, "Cat2 5")
self._top_row = 3
t5.place_frame(self._top_row)
self._top_level.title(title)
def _buildTop(self):
"""Private method to build the Top frame of the GUI."""
top_frame = Tkinter.Frame(self._top_level, name='top_frame')
anchor(top_frame, 1, 3)
top_frame.columnconfigure(0, weight=2)
top_frame.columnconfigure(1, weight=5)
col1_label = Tkinter.Label(top_frame
, name='col1_label'
, text="Col1"
, font=bold_12
, width=20
).grid(row=0
, column=0
, sticky=N+E+W+S
)
col2_label = Tkinter.Label(top_frame
, name='col2_label'
, text="Col2"
, font=bold_12
, width=40
).grid(row=0
, column=1
, sticky=N+E+W+S
)
top_button = Tkinter.Button(top_frame
, name='top_button'
, text='Top Button'
, font=bold_
).grid(row=0
, column=2
, sticky=E
)
top_frame.grid(row=self._top_row, column=0, sticky=N+W)
def _buildCat1(self):
"""Private method to build the Cat1 frame of the GUI"""
cat1_frame = Tkinter.Frame(self._top_level, name='cat1_frame')
anchor(cat1_frame, 3, 3)
cur_row = 0
cat1_frame.columnconfigure(2, weight=6)
Tkinter.Label(cat1_frame
, name='cat1_label'
, text='Cat1'
, font=bold_
).grid(row=cur_row, column=0, sticky=N+E+W+S)
cat1_size = Tkinter.Text(cat1_frame
, name='cat1_size'
, state=DISABLED
, font=font_
, height=1
, width=10
).grid(row=cur_row
, column=1
, sticky=E
)
cat1_status = Tkinter.Text(cat1_frame
, name='cat1_status'
, state=DISABLED
, font=font_
, height=3
, width=72
).grid(row=cur_row
, column=2
, rowspan=3
, sticky=N+E+W+S
)
cur_row += 1
cat1_model = Tkinter.Text(cat1_frame
, name='cat1_model'
, state=DISABLED
, font=font_
, height=1
, width=30
).grid(row=cur_row
, column=0
, columnspan=2
, sticky=N+W
)
cur_row += 1
cat1_serial = Tkinter.Text(cat1_frame
, name='cat1_serial'
, state=DISABLED
, font=font_
, height=1
, width=30
).grid(row=cur_row
, column=0
, columnspan=2
, sticky=N+W
)
cat1_frame.grid(row=self._top_row, column=0, sticky=N+W)
class Cat2Frame():
"""Class encapsulation for a Cat2 Frame in the GUI"""
def __init__(self, parent, t_label):
"""Initialize a Cat2 Frame in the GUI"""
self._frame = Tkinter.Frame(parent, name='cat2_frame')
anchor(self._frame, 3, 4)
self.cur_row = 0
self._frame.columnconfigure(2, weight=5)
self._label = Tkinter.Label(self._frame
, name='cat2_label'
, text=t_label
, font=bold_
)
self._size = Tkinter.Text(self._frame
, name='cat2_size'
, state=DISABLED
, font=font_
, height=1
, width=10
)
self._status = Tkinter.Text(self._frame
, name='cat2_status'
, state=DISABLED
, font=font_
, height=3
, width=60
)
self._control = Tkinter.IntVar()
self._enabled = Tkinter.Radiobutton(self._frame
, name='cat2_enabled'
, variable=self._control
, text='Enabled'
, font=bold_
, value=1
)
self._model = Tkinter.Text(self._frame
, name='cat2_model'
, state=DISABLED
, font=font_
, height=1
, width=30
)
self._disabled = Tkinter.Radiobutton(self._frame
, name='cat2_disabled'
, variable=self._control
, text='Disabled'
, font=bold_
, value=0
)
self._serial = Tkinter.Text(self._frame
, name='cat2_serial'
, state=DISABLED
, font=font_
, height=1
, width=30
)
def place_frame(self, top_row):
self._label.grid(row=self.cur_row, column=0, sticky=N+E+S+W)
self._size.grid(row=self.cur_row, column=1, sticky=E)
self._status.grid(row=self.cur_row, column=2, rowspan=3, sticky=N+E+W+S)
self._enabled.grid(row=self.cur_row, column=3, sticky=W)
self.cur_row += 1
self._model.grid(row=self.cur_row, column=0, columnspan=2, sticky=N+W)
self._disabled.grid(row=self.cur_row, column=3, sticky=W)
self.cur_row += 1
self._serial.grid(row=self.cur_row, column=0, columnspan=2, sticky=N+W)
self.cur_row += 1
self._frame.grid(row=top_row, column=0, sticky=N+W)
答案 0 :(得分:3)
您的代码的简短答案是您为两个Cat2Frame对象指定了相同的名称。要么给它们唯一的名称,要么不要使用框架的name属性。
另外,我建议你重新考虑一下你的编程风格吗?你编写代码的方式很难阅读。我发现将布局与窗口小部件创建分开有助于实现,并且可能更容易找到这个错误(因为能够一目了然地看到所有布局以确定它是正确的)。
这是一个快速入侵,展示如何重构代码以使其更具可读性。我不是说这是重构代码的最好方法,我只是把它作为思考的食物。
我假设您希望所有行都布置在单个网格中,因此您的每个“帧”(Cat1Frame,Cat2Frame)都不是实际帧,因为很难将单元格对齐小部件。如果不是这种情况(即:如果每个“Frame”真的是一个独立的小部件),代码可以变得更简单。
我没有花时间创建顶行,也没有花时间让所有行和列完全正确调整大小。我还给每个文本小部件一个背景,这样你就可以看到它们是如何布局的。我发现当您可以看到小部件的边界时,解决布局问题会更加简单。
import Tkinter
from Tkinter import DISABLED
_TITLE="This is the title"
class TkinterGui():
def __init__(self):
self._buildGui(_TITLE)
self.last_row = 0
def _buildGui(self, title):
self._top_level = Tkinter.Tk()
self._top_level.title(title)
Cat1(self._top_level, label="Cat 1", row=1)
Cat2(self._top_level, label="Cat 2.1", row=4)
Cat2(self._top_level, label="Cat 2.2", row=7)
class Cat1:
def __init__(self, parent, label=None, row=0):
self._label = Tkinter.Label(parent, text=label)
self._size = Tkinter.Text(parent, state=DISABLED, height=1, width=10, background="bisque")
self._status = Tkinter.Text(parent, state=DISABLED, height=3, width=72, background="bisque")
self._model = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
self._serial = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
self._label.grid( row=row, column=0, sticky="nsew")
self._size.grid( row=row, column=1, sticky="nsew")
self._status.grid(row=row, column=2, rowspan=3, sticky="nsew")
self._model.grid( row=row+1, column=0, columnspan=2, sticky="nsew")
self._serial.grid(row=row+2, column=0, columnspan=2, sticky="nsew")
class Cat2:
def __init__(self, parent, label=None, row=0):
self._control = Tkinter.IntVar()
self._label = Tkinter.Label(parent, text=label)
self._size = Tkinter.Text(parent, state=DISABLED, height=1, width=10, background="bisque")
self._status = Tkinter.Text(parent, state=DISABLED, height=3, width=72, background="bisque")
self._model = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
self._serial = Tkinter.Text(parent, state=DISABLED, height=1, width=30, background="bisque")
self._enabled = Tkinter.Radiobutton(parent, variable=self._control, text="Enabled", value=1)
self._disabled = Tkinter.Radiobutton(parent, variable=self._control, text="Disabled", value=0)
self._label.grid( row=row, column=0, sticky="nsew")
self._size.grid( row=row, column=1, sticky="nsew")
self._status.grid( row=row, column=2, rowspan=3, sticky="nsew")
self._model.grid( row=row+1, column=0, columnspan=2, sticky="nsew")
self._serial.grid( row=row+2, column=0, columnspan=2, sticky="nsew")
self._enabled.grid( row=row, column=3, sticky="nsew")
self._disabled.grid(row=row+1, column=3, sticky="nsew")
if __name__ == "__main__":
gui=TkinterGui()
gui._top_level.mainloop()