在使用 Tkinter 创建一个具有用户输入变量的 GUI 时,我们需要能够根据唯一的 ID 动态添加和删除子框架。这些子框架包含一些用户需要输入的变量,这些变量在将来需要通过唯一的 ID 来获取。
在这个问题中,我们遇到了三个具体的问题:
-
为什么显示每个框架标题的 Label 控件没有显示?
-
为什么有时需要按两次添加或删除按钮才能添加或删除框架?
-
在这种情况下,是否有更好的方法来跟踪框架实例(目前使用列表来跟踪)?
-
解决方案
针对以上问题,解决方案如下:
-
显示标题:
这个问题的原因是,在创建
Label控件时,没有使用适当的text参数。正确的方法是使用StringVar()变量来设置文本,然后将其传递给textvariable参数。 -
避免需要按两次按钮:
这个问题的原因是,在添加或删除框架时,没有正确地更新
self.number和self.sub_frame的值。 -
选择更合适的数据结构来跟踪框架实例:
为了更好地跟踪框架实例,可以使用一个具有适当方法的类来管理框架。这样可以更轻松地添加、删除和访问框架。
以下是一个改进的代码示例:
-
import tkinter as tk
class FrameGroup(tk.Frame): def init(self, parent): tk.Frame.init(self, parent) self.all_instances = [] self.counter = 0
def Add(self):
self.counter += 1
name = "Frame %s" % self.counter
subframe = Subframe(self, name=name)
subframe.pack(side="left", fill="y")
self.all_instances.append(subframe)
def Remove(self, instance):
# don't allow the user to destroy the last item
if len(self.all_instances) > 1:
index = self.all_instances.index(instance)
subframe = self.all_instances.pop(index)
subframe.destroy()
def HowMany(self):
return len(self.all_instances)
def ShowMe(self):
for instance in self.all_instances:
print(instance.get())
class Subframe(tk.Frame): def init(self, parent, name): tk.Frame.init(self, parent) self.parent = parent self.e1 = tk.Entry(self) self.e2 = tk.Entry(self) self.e3 = tk.Entry(self) label = tk.Label(self, text=name, anchor="center") add_button = tk.Button(self, text="Add", command=self.parent.Add) remove_button = tk.Button(self, text="Remove", command=lambda: self.parent.Remove(self))
label.pack(side="top", fill="x")
self.e1.pack(side="top", fill="x")
self.e2.pack(side="top", fill="x")
self.e3.pack(side="top", fill="x")
add_button.pack(side="top")
remove_button.pack(side="top")
def get(self):
return (self.e1.get(), self.e2.get(), self.e3.get())
class GUI(tk.Tk): def init(self): tk.Tk.init(self) self.master_frame = tk.Frame(self) self.master_frame.grid() self.all_instances = FrameGroup(self.master_frame) self.all_instances.grid()
# create the first frame
self.all_instances.Add()
root = GUI() root.mainloop()
这个改进的代码示例解决了前面提到的问题。在 `Subframe` 类中,我们创建了 `get()` 方法来获取框架中用户输入的值。在 `FrameGroup` 类中,我们创建了 `Add()` 和 `Remove()` 方法来添加和删除框架。
通过这些改进,我们可以轻松地动态添加和删除框架,并使用 `FrameGroup` 类来管理和跟踪框架实例。