我正在使用tkinter创建一个GUI应用程序。我有多个选项卡,其中一个选项卡是一组单选按钮,允许用户选择他们要输入的内容,这些内容存储在树形视图中。根据用户选择的单选按钮,将动态创建标签,输入框和将输入添加到树中的按钮(每个单选按钮在GUI中需要不同数量的输入和布局)。所有这些都很好。请注意,我在树上预先填充了1个条目,如果要添加新条目,用户可以选择该条目(以后变得很重要)。
我遇到的问题是用户是否要删除或更新条目。我有代码,允许他们从树中选择一个项目,并重新填充正确的标签和输入框(及其当前值)。但是,我也想删除“添加”按钮,将其替换为“更新”按钮,并创建一个“删除”按钮。我也有一些代码。我使用.winfo_exists()函数来确定屏幕上有哪些按钮,并设置一个标志来确定应如何设置新按钮。
当我单击单选按钮时,一切都会更新。当我单击树中的现有条目时,一切也都很好。如果用户单击我前面提到的树中的“新条目”项,就会出现问题。每次单击“新条目”项时,.winfo_exists()函数都会看到“更新”按钮存在(意味着应将其替换为“添加”按钮),但是它返回的值为0,因此我的标志设置不正确更新按钮。
我有大量的打印语句来尝试并跟踪代码的进展情况,我可以看到该标志未正确设置,但我不知道为什么。我想念什么?
下面是代码的最低版本(似乎有点长,但是我可以做到的很短)。我的基本测试用例是只向树添加1个条目。我单击该条目,一切都很好。然后,我单击“(新)”,它无法正确更新。
预先感谢您的帮助。
import tkinter as tk
from tkinter import ttk
import numpy as np
class MainGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('Title')
self.geometry('750x500')
# Adds tabs to main window
self.nb = ttk.Notebook(self)
self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
self.tab1 = ttk.Frame(self.nb)
self.nb.add(self.tab1, text='Tab1')
self.tab2 = ttk.Frame(self.nb)
self.nb.add(self.tab2, text='Tab2')
# defines a grid 50 x 50 cells in the main window & tabs
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
tab1_r = 10
tab1_c = 4
tab2_r = 8
tab2_c = 4
for i in range(tab1_r):
self.tab1.rowconfigure(i, weight=1)
for i in range(tab1_c):
self.tab1.columnconfigure(i, weight=1)
for i in range(tab2_r):
self.tab2.rowconfigure(i, weight=1)
for i in range(tab2_c):
self.tab2.columnconfigure(i, weight=1)
self.tab1Label = tk.Label(self.tab1, text="This is a Label")
self.tab1Label.grid(column=0, row=0, sticky='NW')
self.tab1Label2 = tk.Label(self.tab1, text="This is also a Label")
self.tab1Label2.grid(column=0, row=1, sticky='NW')
self.types = [('Thing1'), ('Thing2')]
self.pType = tk.StringVar()
self.pType.set("Thing1") # initialize
col = 0
for text in self.types:
self.rBtn = tk.Radiobutton(self.tab2, text=text, variable=self.pType, value=text, command=self.makeWidgets)
self.rBtn.grid(column=col, row=6, sticky='E')
col += 1
self.makeTable()
self.makeWidgets()
def makeWidgets(self):
try:
for self.label in self.Labels:
self.label.destroy()
except AttributeError:
pass
try:
for self.entry in self.Entries:
self.entry.destroy()
except AttributeError:
pass
try:
self.addBtn.destroy()
except AttributeError:
pass
try:
self.delBtn.destroy()
except AttributeError:
pass
try:
self.updtBtn.destroy()
except AttributeError:
pass
self.Labels = []
self.Entries = []
if(self.pType.get() == "Thing1"):
self.labText = [('Add to Table:')]
elif(self.pType.get() == "Thing2"):
self.labText = [('Add to Table:'), ('Also add to Table:')]
self.xGrid = 1
self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
i = 0
for j in range(0, self.xGrid + 1, 2):
for k in range(self.yGrid):
if(i == len(self.labText)):
break
else:
self.label = tk.Label(self.tab2, text=self.labText[i])
self.label.grid(column=j, row=k + 8, sticky='SW')
self.Labels.append(self.label)
self.entry = tk.Entry(self.tab2)
self.entry.insert(0, '0.0000')
self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
self.Entries.append(self.entry)
i += 1
self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')
self.tree.focus(self.tree.get_children()[0])
self.tree.selection_set(self.tree.get_children()[0])
def makeTable(self):
tab_header = ['Pattern #', 'Description']
self.tree = ttk.Treeview(self.tab2, columns=tab_header, height=5, show="headings")
vsb = ttk.Scrollbar(self.tab2, orient="vertical", command=self.tree.yview)
self.tree.configure(yscrollcommand=vsb.set)
self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
vsb.grid(column=1, row=0, rowspan=5, sticky='ENS')
self.tree.heading(tab_header[0], text=tab_header[0].title())
self.tree.column(tab_header[0], width=30, anchor='center')
self.tree.heading(tab_header[1], text=tab_header[1].title())
self.tree.column(tab_header[1], width=170, anchor='center')
self.tree.insert('', 'end', values=("", "(new)"))
self.tree.bind("<ButtonRelease-1>", self.getPtrnTable)
self.counter = 1
print(type(self.counter))
def addEntry(self):
if(self.pType.get() == "Thing1"):
self.description = self.pType.get() + ": " + self.Entries[0].get()
elif(self.pType.get() == "Thing2"):
self.description = self.pType.get() + ": " + self.Entries[0].get() + " and " + self.Entries[1].get()
self.tree.insert('', 'end', values=(self.counter, self.description))
self.counter += 1
print(self.counter)
print(type(self.counter))
self.nominalTableSelect()
self.repopEntries()
def delEntry(self):
treeCnt = len(self.tree.get_children())
items = self.tree.get_children()
for i in range(int(self.patNum), treeCnt - 1):
self.tree.set(items[i], 'Description', self.tree.item(items[i + 1], 'values')[1])
self.tree.delete(items[-1])
self.nominalTableSelect()
self.updateButtons()
def updateEntry(self):
pass
def getPtrnTable(self, event):
self.item = self.tree.identify_row(event.y)
try:
self.patNum = self.tree.item(self.item, 'values')[0]
except IndexError:
self.patNum = ''
self.repopEntries()
self.updateButtons()
def nominalTableSelect(self):
self.tree.focus(self.tree.get_children()[0])
self.tree.selection_set(self.tree.get_children()[0])
self.item = self.tree.get_children()[0]
self.patNum = self.tree.item(self.item, 'values')[0]
def repopEntries(self):
try:
if(self.tree.item(self.item, 'values')[1] == '(new)'):
self.pType.set("Thing1")
self.makeWidgets()
print("Repopulate with New/Blank Entries...")
else:
self.thing, junk = self.tree.item(self.item, 'values')[1].split(":")
self.iNum = int(self.tree.item(self.item, 'values')[0]) - 1
self.pType.set(str(self.thing))
self.makeWidgets() # restore correct label/entry layout
self.tree.focus(self.item)
self.tree.selection_set(self.item)
print("Repopulate with DATA...")
# some code here to repopulate entry boxes from stored data
except (IndexError, NameError, AttributeError):
pass
def updateButtons(self):
print("")
print("")
print("Update Buttons...")
print("")
add = 0
update = 0
try:
add = self.updtBtn.winfo_exists()
print("Update Button Exists...")
print("Set ADD flag to: ", add)
except (AttributeError, NameError):
print("Update Button Does NOT Exist.")
try:
update = self.addBtn.winfo_exists()
print("Add Button Exists...")
print("Set UPDATE flag to: ", update)
except (AttributeError, NameError):
print("Add Button Does NOT Exist")
print("")
print("add = ", add)
print("update = ", update)
print("Item to be Checked is: ", self.tree.item(self.item, 'values')[1])
print("")
if(len(self.tree.get_children()) == 1):
print("Nothing in Tree...do nothing.")
else:
if(update == 1): # Add Button Exists - Change to Update
print("Change to Update Button...")
self.btnLoc = self.addBtn.grid_info()
print("Add Button Location: ", self.btnLoc)
print("Destroy Add, Replace with Update...")
self.addBtn.destroy()
print("Add Button Status: ", self.addBtn.winfo_exists())
self.updtBtn = tk.Button(self.tab2, text='Update Pattern', command=self.updateEntry)
self.updtBtn.grid(column=int(self.btnLoc["column"]), row=int(self.btnLoc["row"]), sticky='NSEW')
self.delBtn = tk.Button(self.tab2, text='Delete Pattern', command=self.delEntry)
self.delBtn.grid(column=int(self.btnLoc["column"]) - 1, row=int(self.btnLoc["row"]), sticky='NSEW')
print("Update Button Status: ", self.updtBtn.winfo_exists())
print("Delete Button Status: ", self.delBtn.winfo_exists())
print("")
elif(add == 1): # Update Button Exists - Change to Add
print("Change to Add Button...")
self.btnLoc = self.updtBtn.grid_info()
print("Update Button Location: ", self.btnLoc)
print("Destroy Update, Replace with Add")
self.updtBtn.destroy()
print("Update Button Status: ", self.updtBtn.winfo_exists())
self.delBtn.destroy()
print("Delete Button Status: ", self.delBtn.winfo_exists())
self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=int(self.btnLoc["column"]), row=int(self.btnLoc["row"]), sticky='NSEW')
print("Add Button Status: ", self.addBtn.winfo_exists())
def main():
MainGUI().mainloop()
if __name__ == '__main__':
main()
答案 0 :(得分:0)
虽然我仍然不能确定始终正确设置该标志(使用.winfo_exists()函数),但我仍能得到一个可行的解决方案。通过向updateButtons模块添加另一个条件检查,我检查是否选择了树中的默认“ New Item”,如果是,我只是使用原始按钮为新条目重新填充页面(使用repopEntries模块)。 / p>
def updateButtons(self):
add = 0
update = 0
try:
add = self.updtBtn.winfo_exists()
except (AttributeError, NameError):
pass
try:
update = self.addBtn.winfo_exists()
except (AttributeError, NameError):
pass
if(len(self.tree.get_children()) == 1):
pass
elif(self.tree.item(self.item, 'values')[1] == '(new)'):
self.repopEntries()
else:
if(update == 1): # Add Button Exists - Change to Update
self.btnLoc = self.addBtn.grid_info()
self.addBtn.destroy()
self.updtBtn = tk.Button(self.tab2, text='Update Pattern', command=self.updateEntry)
self.updtBtn.grid(column=int(self.btnLoc["column"]), row=int(self.btnLoc["row"]), sticky='NSEW')
self.delBtn = tk.Button(self.tab2, text='Delete Pattern', command=self.delEntry)
self.delBtn.grid(column=int(self.btnLoc["column"]) - 1, row=int(self.btnLoc["row"]), sticky='NSEW')
elif(add == 1): # Update Button Exists - Change to Add
self.btnLoc = self.updtBtn.grid_info()
self.updtBtn.destroy()
self.delBtn.destroy()
self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=int(self.btnLoc["column"]), row=int(self.btnLoc["row"]), sticky='NSEW')
关于.winfo_exists()函数或我对它的理解的任何评论仍将不胜感激。