【发布时间】:2019-08-20 21:36:41
【问题描述】:
我是 Python 和 tkinter 的新手,我正在尝试用它创建一个 GUI。我正在尝试根据第一个组合框的选择创建新的标签和组合框。我已经完成了第一个可选组合框的创建,并根据在第一个组合框中选择的选项绑定了新标签和组合框的创建。
但是,由于不同的选择会创建不同数量的标签和组合框,并且其中一些位于框架的相同位置,因此标签和组合框可能会重叠,从而导致用户阅读混乱。主要问题在于“def createSystem(self,event)”函数,因为这里使用了两个for循环,我不知道如何清除第一个“if条件”在创建之前创建的旧标签/组合框当程序满足第二个“如果条件”时,新的。
到目前为止,我尝试了两种解决方案,但都没有成功。
我尝试创建一个全局列表并将私有函数中创建的所有标签推送到其中,以便我可以使用 label.destory() 清除所有标签并创建新标签。但是,问题在于我不知道如何将正在创建的标签添加到列表中,以及如何在第二个 for 循环开始创建新标签之前删除。
我想过直接修改特定行的现有标签的文本,但是由于标签是使用函数'ttk.Label()'直接创建的,没有分配给任何变量,所以我不能解决它们并对它们进行一些修改。如果我想将它们分配给不同的变量,我将需要在 for 循环中同时创建变量,尽管在 Python 中是可行的,但我在 Google 上搜索过据说是一件坏事。
import tkinter as tk
from tkinter import ttk
cc_category = {'zxcv': ["vzxcv"], 'qeqL': ["safx"]}
ab_type = ["sfda", "fsdf"]
bbbbList = {
'sddd':["1","2","3","4"],
'ssss sdddd':["1", "2", "3", "4", "5", "6", "2500", "4500"],
'assss sssaz':["BA", "BB", "BC", "BD", "BE", "BF", "BWD", "BWA"],
'asdf Cfsdfsddf':["1"],
'asdf fasdfs' :["1"],
'asdf zxxxxxx':["1"],
'cccc xxxxxxx':["1"],
'cccc saddddL':["1","2","4","42","2"],
'zxxx xvzzzzL':["1","2","3"],
'cvcv cccxxxc':["2","2","EPDM","3","3","4","4","82","122","333"],
}
aaaaLabelList = {'wwww':[],
'qqqq':[],
'hjfgjhk':[],
'xzvxzcvx':[],
'qweaddddz':[],
'qweasd':[],
'utyiuiufturt':[],
'zxcvxzbvc':[],
'fdass':[],
'ffdasdd':[],
'fsdfaL':[],
'fdasfzxAL':[],
'fdsafdL':[],
'Dasdfszxd':[],
'dasfsdfsadE':[],
'FIRE SAFE':[],
'rrrr':[],
'eeee':[]}
framelist = []
frames = 1
labellist = [20]
class Root (tk.Tk):
def __init__(self):
super(Root, self).__init__()
self.title("sssssss")
self.minsize(640, 400)
self.InitUI()
def getUpdateData(self, event):
self.cb['values'] = cc_category[self.ValveTypeCombo.get()]
def add_frame(self):
global frames
framelist.append(tk.Frame(root))
framelist[-1].grid()
frames += 1
def delete_frame(self):
global frames
framelist.remove(tk.Frame(root))
framelist[-1].detory()
frames -= 1
def createSystem(self, event):
if self.labelCombo.get() == "zxcv":
for labelname in bbbbList:
ttk.Label(self, text = labelname + ": ").grid(column = 0, row = list(bbbbList).index(labelname) + 2)
ttk.Combobox(self, width = 10, state = 'readonly', values = bbbbList.get(labelname)).grid(column = 1, row = list(bbbbList).index(labelname) + 2)
if self.labelCombo.get() == "qeqL":
for labelname in aaaaLabelList:
ttk.Label(self, text = labelname + ": ").grid(column = 0, row = list(aaaaLabelList).index(labelname) + 2)
ttk.Combobox(self, width = 10, state = 'readonly', values = aaaaLabelList.get(labelname)).grid(column = 1, row = list(aaaaLabelList).index(labelname) + 2)
def InitUI(self):
self.label_1 = ttk.Label(self,text = "asss dddd: ")
self.label_1.grid(column = 0, row = 0)
self.labelCombo = ttk.Combobox(self, width = 5, state = 'readonly', values = list(cc_category.keys()))
self.labelCombo.bind('<<ComboboxSelected>>', self.createSystem)
self.labelCombo.grid(column = 1, row = 0)
if __name__== '__main__':
root = Root()
root.mainloop()
以下是我编写的代码,用于将在 for 循环中创建的标签传递给全局列表。但它有一个编译错误:
line 77, in createSystem
labellist[i].grid(column = 0, row = list(bbbbList).index(labelname) + 2)
AttributeError: 'int' object has no attribute 'grid'
我不知道该怎么处理。
以下是我第一个想法的完整代码:
import tkinter as tk
from tkinter import ttk
cc_category = {'zxcv': ["vzxcv"], 'qeqL': ["safx"]}
ab_type = ["sfda", "fsdf"]
bbbbList = {
'sddd':["1","2","3","4"],
'ssss sdddd':["1", "2", "3", "4", "5", "6", "2500", "4500"],
'assss sssaz':["BA", "BB", "BC", "BD", "BE", "BF", "BWD", "BWA"],
'asdf Cfsdfsddf':["1"],
'asdf fasdfs' :["1"],
'asdf zxxxxxx':["1"],
'cccc xxxxxxx':["1"],
'cccc saddddL':["1","2","4","42","2"],
'zxxx xvzzzzL':["1","2","3"],
'cvcv cccxxxc':["2","2","EPDM","3","3","4","4","82","122","333"],
}
aaaaLabelList = {'wwww':[],
'qqqq':[],
'hjfgjhk':[],
'xzvxzcvx':[],
'qweaddddz':[],
'qweasd':[],
'utyiuiufturt':[],
'zxcvxzbvc':[],
'fdass':[],
'ffdasdd':[],
'fsdfaL':[],
'fdasfzxAL':[],
'fdsafdL':[],
'Dasdfszxd':[],
'dasfsdfsadE':[],
'FIRE SAFE':[],
'rrrr':[],
'eeee':[]}
framelist = []
frames = 1
labellist = [20]
class Root (tk.Tk):
def __init__(self):
super(Root, self).__init__()
self.title("sssssss")
self.minsize(640, 400)
self.InitUI()
def getUpdateData(self, event):
self.cb['values'] = cc_category[self.ValveTypeCombo.get()]
def add_frame(self):
global frames
framelist.append(tk.Frame(root))
framelist[-1].grid()
frames += 1
def delete_frame(self):
global frames
framelist.remove(tk.Frame(root))
framelist[-1].detory()
frames -= 1
def createSystem(self, event):
if self.labelCombo.get() == "zxcv":
for i, labelname in zip(range(20),bbbbList):
root.add_frame()
labellist.append(tk.Frame(root))
ttk.Label(framelist[i], text = labelname + ": ")
labellist[i].grid(column = 0, row = list(bbbbList).index(labelname) + 2)
ttk.Combobox(self, width = 10, state = 'readonly', values = bbbbList.get(labelname)).grid(column = 1, row = list(bbbbList).index(labelname) + 2)
i += 1
if self.labelCombo.get() == "qeqL":
for labelname in aaaaLabelList:
ttk.Label(self, text = labelname + ": ").grid(column = 0, row = list(aaaaLabelList).index(labelname) + 2)
ttk.Combobox(self, width = 10, state = 'readonly', values = aaaaLabelList.get(labelname)).grid(column = 1, row = list(aaaaLabelList).index(labelname) + 2)
def InitUI(self):
self.label_1 = ttk.Label(self,text = "asss dddd: ")
self.label_1.grid(column = 0, row = 0)
self.labelCombo = ttk.Combobox(self, width = 5, state = 'readonly', values = list(cc_category.keys()))
self.labelCombo.bind('<<ComboboxSelected>>', self.createSystem)
self.labelCombo.grid(column = 1, row = 0)
if __name__== '__main__':
root = Root()
root.mainloop()
当我同时切换在第一个组合框中选择的值时,我希望看到标签和组合框不会相互重叠,从而能够访问在所有新创建的组合框中选择的值以进一步采用。例如,我可以创建一个提交按钮来提交在选择第一个组合框之后创建的组合框中选择的所有值。
已编辑
我已经编辑了createSystem函数,现在可以编译了,但问题是似乎一直在给'framelist[]'添加标签,我试图在for中添加'framelist[i].destroy()循环销毁当前标签,但它返回
AttributeError: '_tkinter.tkapp' object has no attribute 'framelist'
这是新的“createSystem”函数的代码:
def createSystem(self, event):
if self.labelCombo.get() == "zxcv":
for i, labelname in zip(range(len(bbbbList)),bbbbList):
root.add_frame()
#labellist.append(tk.Frame(root))
ttk.Label(framelist[i], text = labelname).grid()
ttk.Combobox(self, width = 10, state = 'readonly', values = bbbbList.get(labelname)).grid(column = 1, row = i + 1)
if self.labelCombo.get() == "qeqL":
for i, labelname in zip(range(len(aaaaLabelList)),aaaaLabelList):
ttk.Label(self, text = labelname + ": ").grid(column = 0, row = list(aaaaLabelList).index(labelname) + 2)
ttk.Combobox(self, width = 10, state = 'readonly', values = aaaaLabelList.get(labelname)).grid(column = 1, row = list(aaaaLabelList).index(labelname) + 2)
【问题讨论】:
-
你的
labellist是[20]所以你尝试做20.grid(...)并且你得到错误'int' object has no attribute 'grid' -
@furas 感谢您的回复,我已经编辑了它,现在似乎可以工作了,现在可以将标签添加到框架列表中。但是,我仍然无法销毁列表中的标签,并且每次在第一个组合框中的两个选项之间切换时,它都会不断向框架列表中添加新标签。我知道这是因为每次我从第一个组合框中选择一个项目时,它都会创建新标签,但问题是我不知道如何删除存储在框架列表中的标签,你知道如何解决它们吗?删除它们?谢谢。
-
当您尝试
destroy()列表中的每个标签时是否收到错误消息?销毁标签后,您可能也必须将其从列表中删除 -list.pop(index)或del list[index]。如果您删除所有标签,那么(在销毁所有标签后)您可以将空列表分配给变量。
标签: python tkinter label overlay