Tkinter Radiobutton类结构下点击按钮输出空值问题求助
Tkinter单选按钮选中值无法获取的问题解决
我正在学习Tkinter,想要创建一个包含若干Radiobutton和一个按钮的窗口,点击按钮时在终端打印Radiobutton的选中项。我将代码用类的形式组织,但点击按钮时输出的是空值,多次点击也是如此。若将相关代码单独放到新Python文件中却能正常运行,找不到问题原因及解决办法,恳请帮忙。
出现问题的代码
from tkinter import * from tkinter import ttk from tkinter import messagebox class Window: def __init__(self, master): ttk.Label(master, text="Logo").grid(row=0, column=0, rowspan=2) ttk.Button(master, text="Login", command=self.login).grid(row=0, column=1) ttk.Button(master, text="Register", command=self.register).grid(row=1, column=1) def login(self): root = Tk() login_window = Login(root) root.mainloop() def register(self): root = Tk() register_window = Register(root) root.mainloop() class Login: def __init__(self, master): r = StringVar() ttk.Radiobutton(master, value="1", variable=r, text="1").grid(row=0, column=0) ttk.Radiobutton(master, value="2", variable=r, text="2").grid(row=1, column=0) ttk.Radiobutton(master, value="3", variable=r, text="3").grid(row=2, column=0) ttk.Radiobutton(master, value="4", variable=r, text="4").grid(row=3, column=0) ttk.Button(master, text="Select", command=lambda: self.button_select(r.get())).grid(row=0, column=1, rowspan=4) def button_select(self, selection): print(selection) class Register: def __init__(self, master): pass def main(): root = Tk() main_window = Window(root) root.mainloop() if __name__ == '__main__': main()
单独抽离后正常运行的代码
from tkinter import * from tkinter import ttk def button_select(selection): print(selection) master = Tk() r = StringVar() ttk.Radiobutton(master, value="1", variable=r, text="1").grid(row=0, column=0) ttk.Radiobutton(master, value="2", variable=r, text="2").grid(row=1, column=0) ttk.Radiobutton(master, value="3", variable=r, text="3").grid(row=2, column=0) ttk.Radiobutton(master, value="4", variable=r, text="4").grid(row=3, column=0) ttk.Button(master, text="Select", command=lambda: button_select(r.get())).grid(row=0, column=1, rowspan=4) master.mainloop()
问题原因
问题出在Login类的__init__方法中,r = StringVar()是局部变量。当__init__方法执行完毕后,这个局部变量会被Python的垃圾回收机制清理,导致单选按钮的variable关联失效,无法获取选中值。而单独运行的代码中,r是全局变量,生命周期和程序一致,不会被回收,因此能正常工作。
解决办法
将r定义为Login类的实例属性,让它和类实例绑定,避免被垃圾回收。修改后的Login类代码如下:
class Login: def __init__(self, master): # 将r改为实例属性 self.r = StringVar() ttk.Radiobutton(master, value="1", variable=self.r, text="1").grid(row=0, column=0) ttk.Radiobutton(master, value="2", variable=self.r, text="2").grid(row=1, column=0) ttk.Radiobutton(master, value="3", variable=self.r, text="3").grid(row=2, column=0) ttk.Radiobutton(master, value="4", variable=self.r, text="4").grid(row=3, column=0) # 调用时使用self.r.get() ttk.Button(master, text="Select", command=lambda: self.button_select(self.r.get())).grid(row=0, column=1, rowspan=4) def button_select(self, selection): print(selection)
额外优化建议
Tkinter应用中建议只创建一个主Tk()实例,新窗口使用Toplevel()代替重复创建Tk(),避免多个主循环引发的问题。比如修改Window类的login方法:
def login(self): # 用Toplevel创建子窗口,无需额外调用mainloop() root = Toplevel() login_window = Login(root)
内容的提问来源于stack exchange,提问作者geolyk
相关产品推荐
相关产品推荐

