python - Tkinter 为每个单选按钮返回相同的值?
问题描述
我正在使用 Tkinter 弹出一个自定义对话框。我正在从另一个 Tkinter 窗口打开它。
root = Tk()
class ListDialog:
def __init__(self, names, prompt):
self.names = names
self.sub_root = Tk()
self.sub_root.title("Intovex")
self.sub_root.iconbitmap("Icon.ico")
self.myfont = Font(root=self.sub_root, family="Arial", size=8)
self.sub_root.maxsize(320, 240)
self.sub_root.wm_attributes("-topmost", True)
self.sub_root.wm_attributes("-toolwindow", True)
self.var = IntVar()
label = Label(self.sub_root, text=prompt)
label.pack(fill=X)
c=1
print(names)
for i in names:
print(i)
r = Radiobutton(self.sub_root, text=i, variable=self.var, value=c, command=self.end)
r.pack(anchor=W)
c+=1
self.var.set(1)
button = Button(self.sub_root, command=self.endit, text="OK", bg = "#448DE0", fg="White", bd=0, width=12, pady=4, padx=4, height=1,font=self.myfont, highlightcolor="#A3C7F0")
button.pack(side=BOTTOM)
self.choice = names[0]
def end(self):
ch = self.var.get()
print(str(ch))
self.choice = self.names[ch - 1]
def endit(self):
self.sub_root.destroy()
def ask(self):
self.sub_root.mainloop()
var2 = StringVar()
def get_choice():
list = ListDialog(["Test1", "Test2"], "Testing")
list.ask()
var2.set(str(list.choice))
label = Label(root, text="", textvariable=var2)
button = Button(root, text="Test", command=get_choice)
label.pack()
button.pack()
root.mainloop()
但是,当它通过直接实例化类并调用 ask() 方法单独运行时,它可以工作。您可能已经看到我在代码中到处都有打印语句(用于调试),我发现它在哪里不起作用
- 打印列表参数的打印语句
names
正确打印整个列表。 - 在 for 循环内部,它也会
names
正确打印列表中的元素 - 当我单击单选按钮时,它会调用该
end()
方法。它总是在那里打印默认值。
root = Tk()
class ListDialog:
def __init__(self, names, prompt):
self.names = names
self.sub_root = Tk()
self.sub_root.title("Intovex")
self.sub_root.iconbitmap("Icon.ico")
self.myfont = Font(root=self.sub_root, family="Arial", size=8)
self.sub_root.maxsize(320, 240)
self.sub_root.wm_attributes("-topmost", True)
self.sub_root.wm_attributes("-toolwindow", True)
self.var = IntVar()
label = Label(self.sub_root, text=prompt)
label.pack(fill=X)
c=1
print(names)
for i in names:
print(i)
r = Radiobutton(self.sub_root, text=i, variable=self.var, value=c, command=self.end)
r.pack(anchor=W)
c+=1
self.var.set(1)
button = Button(self.sub_root, command=self.endit, text="OK", bg = "#448DE0", fg="White", bd=0, width=12, pady=4, padx=4, height=1,font=self.myfont, highlightcolor="#A3C7F0")
button.pack(side=BOTTOM)
self.choice = names[0]
def end(self):
ch = self.var.get()
print(str(ch))
self.choice = self.names[ch - 1]
def endit(self):
self.sub_root.destroy()
def ask(self):
self.sub_root.mainloop()
list = ListDialog(["Test1", "Test2"], "Testing")
list.ask()
print(list.choice)
但如果我将它作为 TopLevel 小部件打开,它就可以工作。但是随后主窗口不会等到弹出窗口返回值(选择)。
解决方案
第一个片段中的代码的问题是因为您在Tk()
tkinter 应用程序中调用了更多次 - 它混淆了接口代码并可能导致各种问题,正如您所发现的那样。
如果您将类__init__()
方法内的调用替换为ListDialog
一个 to tk.Toplevel()
,那么您的代码将开始工作。
我还通过更改它来简化for
创建Radiobutton
s 的循环,以便使用内置enumerate()
函数自动保留名称的计数。与此相结合,我设置了IntVar
零的初始值,这不是选择单选按钮将分配给它的值之一。因此,当第ListDialog
一次显示时,它们都不会被选中。它还确保end()
当用户按下其中一个时回调函数将被调用,因此您的应用程序将始终在发生这种情况时得到通知。
请注意,虽然我没有更改它,但您不应该命名变量list
,因为这会隐藏该名称的内置类的名称。一般来说,你应该避免命名任何与现有标准 Python 名称冲突的东西。
from tkinter import *
from tkinter.font import Font
root = Tk()
class ListDialog:
def __init__(self, names, prompt):
self.names = names
# self.sub_root = Tk() # Wrong - don't call Tk() more than once.
root.withdraw() # Hide root window.
self.sub_root = Toplevel() # Create another top-level window.
self.sub_root.title("Intovex")
# self.sub_root.iconbitmap("Icon.ico") # I don't have this file...
self.myfont = Font(root=self.sub_root, family="Arial", size=8)
self.sub_root.maxsize(320, 240)
self.sub_root.wm_attributes("-topmost", True)
self.sub_root.wm_attributes("-toolwindow", True)
self.var = IntVar(value=0) # Define and init value to one *not* produced by btns.
label = Label(self.sub_root, text=prompt)
label.pack(fill=X)
print(names)
for c, name in enumerate(names, start=1):
print(c)
r = Radiobutton(self.sub_root, text=c, variable=self.var, value=c,
command=self.end)
r.pack(anchor=W)
button = Button(self.sub_root, command=self.endit, text="OK", bg = "#448DE0",
fg="White", bd=0, width=12, pady=4, padx=4, height=1,
font=self.myfont, highlightcolor="#A3C7F0")
button.pack(side=BOTTOM)
self.choice = names[0]
def end(self):
ch = self.var.get()
print(str(ch))
self.choice = self.names[ch - 1]
def endit(self):
self.sub_root.destroy()
root.deiconify() # Reshow root window.
def ask(self):
self.sub_root.mainloop()
var2 = StringVar()
def get_choice():
list = ListDialog(["Test1", "Test2"], "Testing")
list.ask()
var2.set(str(list.choice))
label = Label(root, text="", textvariable=var2)
button = Button(root, text="Test", command=get_choice)
label.pack()
button.pack()
root.mainloop()
推荐阅读
- rust - 如何使专业化编译成功?
- google-apps-script - 谷歌日历插件:如何实现“全选”复选框?
- c - 为 C 中的可读性分配“分组”
- python - 是否有任何函数可以使用python删除文件中每一行中的特定字符串
- function - 是否有让 opengraph 动态读取页面/帖子元数据的功能?
- sql - 如何从如下列表中查询:[1,1,1,2,3,4,2,2,5,3]
- matlab - 在 MATLAB 中选择特定日期间隔的方法
- opengl - Compute Shader 只写入一个像素
- django - 没有 sendgrid 的 Django 联系页面
- python - 计算测验分数