我仍然是Python的新手,正在为应用程序创建GUI。在此应用程序中,用户选择他/她想要的元素,并根据他的选择显示必要数量的输入网格。
例如。 Square = 2,Sphere = 1等......
我的问题在于,无论何时用户希望更新,首先让他/她选择Square(因此显示两个输入字段),但之后如果他按下Sphere(仍然显示两个输入字段)。
当新的字段数小于当前的字段数时,grid_forget似乎不起作用。
以下代码的一部分:
def domain_dimensions(self, req_dim):
if self.domain.get() == "Square":
req_dim = 2
elif self.domain.get() == 'Sphere':
req_dim = 1
else:
req_dim = 5
for x in range(0,int(req_dim)):
self.domain_dim = Entry(self)
self.domain_dim.grid(row=11, column=1+int(x))
self.domain_dim.grid_forget() #doesnt seem to forget when value is less on reclick.
self.domain = StringVar()
self.domain.set('Square')
domain_dropdown = OptionMenu(self, self.domain,*neper_domains1, command=self.domain_dimensions).grid(row=10, column=1, columnspan=3)
def domain_dimensions(self, req_dim):
global container
for wid in container:
wid.destroy()
container = []
for type, req_dim in neper_domains.iteritems():
if type == self.domain.get():
for x in range(0,int(req_dim)):
domain_dim = Entry(root)
domain_dim.grid(row=25 + x, column=1)
container.append(domain_dim)
答案 0 :(得分:3)
由于网格的性质,如果给出相同的坐标(行和列),则可以将小部件堆叠在一起。如果你换了包装,你会看到在旧纸盒下面继续创建输入框。
此外,您没有正确使用grid_forget
。您所做的就是忘记在for循环之后创建的最后一个小部件。因此,当您选择square时,您只能获得1个Entry小部件。
此外,如果您不打算将忘记的小部件返回到窗口中,那么我建议您使用destroy
。忘记将窗口小部件值保留在内存中,因此如果您不打算重新使用它,应用程序将继续累积忘记的Entry小部件而不是删除它们。
现在为代码示例。您要做的是删除所有现有的Entry小部件,然后再添加新小部件。 winfo_children
返回窗口小部件中包含的所有窗口小部件的列表。
import tkinter as tk
def onChange(val):
if val == "Square":
r = 2
elif val == "Sphere":
r = 1
else:
r = 5
# Destroys all existing widgets in the container frame
for wid in container.winfo_children():
wid.destroy() # Using destory instead of grid_forget
# Dynamically create Entry widgets in container frame
# Number is equal to r
for x in range(r):
e = tk.Entry(container)
e.grid(row = 1 + x, column = 0)
root = tk.Tk()
root.minsize(200, 200)
options = ["Square", "Sphere", "Other"]
var = tk.StringVar()
var.set("Square")
op_menu = tk.OptionMenu(root, var, *options, command = onChange)
op_menu.grid(row = 0, column = 0)
# Container frame for the Entry widgets
container = tk.Frame(root)
container.grid()
如果要保留不会删除的Entry小部件的值,则可以使用以下内容作为onChange函数。
def onChange(val):
if val == "Square":
r = 2
elif val == "Sphere":
r = 1
else:
r = 5
c = container.winfo_children()
old_r = len(c) # Number of widgets in container frame
# Destroys all excess widgets in the container frame
# Eg. old_r = 5, r = 2 | Last 3 widgets in frame are destroyed
if old_r > r:
for wid in c[r:old_r]:
wid.destroy()
# Dynamically create Entry widgets in container frame
# Only creates extra to meet r value
# Eg. old_r = 2, r = 5 | Creates 3 widgets in frame after original 2
elif old_r < r:
for x in range(old_r, r):
e = tk.Entry(container)
e.grid(row = 1 + x, column = 0)
如果您不想为容器使用新框架。然后有几个选择。
首先,如果您使用的帧只有动态创建的Entry小部件,那么您可以使用if语句排除所有非Entry小部件被销毁。
for wid in container.winfo_children():
if type(wid).__name__ == "Entry":
wid.destroy()
或者您可以将动态创建的条目小部件添加到列表中并迭代它而不是winfo_children
def onChange(val):
...
...
global container # Global is used here because this example is not done using classes
for wid in container:
wid.destroy() # Using destory instead of grid_forget
container = [] # Reset container to empty list
for x in range(r):
e = tk.Entry(root)
e.grid(row = 1 + x, column = 0)
container.append(e) # Append widget to container list
...
...
# Container list for the Entry widgets
container = []