Tkinter:所有单选按钮都被选中

3

弹出窗口截图,显示大多数单选按钮预选中

为什么在这段代码中,当点击按钮打开新窗口时,所有的单选按钮都被选中了?

class CodeButton:
    def __init__(self, root):
        self.btn = Button(root, text="Code",width=20, height=1,bg="white", fg="black")
        self.btn.bind("<Button-1>", make_code_window)
        self.btn.pack() 


def make_code_window(event):
    new_root = Toplevel()
    new_root.minsize(width=300, height=300)
    var = IntVar()
    var.set(0)
    for i in range(8):
        Radiobutton(new_root, text=str(i), variable=var, value=i).pack()


def main():
    root = Tk()
    root.minsize(width=400, height=250)
    CodeButton(root)
    root.mainloop()

如何避免这种情况? - m.mokeev
@abccd:那是一个错误的评估。使用单个变量是放射按钮的预期用法。这就是使它们像放射按钮一样运作的原因。 - Bryan Oakley
2个回答

1
这与在函数中将IntVar存储在本地变量中有关,该变量将在make_code_window()函数返回后立即丢弃。您可以通过使IntVar成为new_root窗口小部件的属性来解决问题,因此它将至少存在于使用它的小部件存在期间。
您示例中的代码在某种意义上不太现实,因为通常人们希望在Python代码的其他地方使用IntVar的当前值,但这是不可能的,因为它仅在创建它的函数执行期间暂时存储在本地变量中。
try:
    from tkinter import *
except ImportError:  # Python 2
    from Tkinter import *

class CodeButton:
    def __init__(self, root):
        self.btn = Button(root, text="Code",width=20, height=1,bg="white", fg="black")
        self.btn.bind("<Button-1>", make_code_window)
        self.btn.pack()


def make_code_window(event):
    new_root = Toplevel()
    new_root.minsize(width=300, height=300)
    var = new_root.var = IntVar()  # changed
    var.set(0)
    for i in range(8):
        Radiobutton(new_root, text=str(i), variable=var, value=i).pack()


def main():
    root = Tk()
    root.minsize(width=400, height=250)
    CodeButton(root)
    root.mainloop()

main()

非常感谢您 :) 我只是一名学生,正在尝试为我的项目创建GUI。 - m.mokeev
在这种情况下,有什么好的方法可以保存变量的值而不是本地保存呢? - m.mokeev
最简单的方法是将IntVar作为全局变量,如果这不会影响你的话。一个更好的方法是避免使用全局变量,但这会稍微复杂一些,这也是为什么很多人不愿意费心的原因。也许我可以发布另一个答案... - martineau
我尝试着将变量与事件一起传递,但这并不容易。这是我第一次使用GUI。 - m.mokeev

0

关于我们在其他答案的评论区讨论的问题,我来跟进一下。)

是的,将IntVar作为事件处理函数的参数传递有点棘手,事实上有时被称为额外参数技巧;-)

以下是将其应用到您的代码的示例:

try:
    from tkinter import *
except ImportError:  # Python 2
    from Tkinter import *


class CodeButton:
    def __init__(self, root):
        self.btn = Button(root, text="Code",width=20, height=1,bg="white", fg="black")
        self.btn.bind("<Button-1>",
                      # Extra Arguments Trick
                      lambda event, var=root.var: make_code_window(event, var))
        self.btn.pack()


def make_code_window(event, var):  # note added "var" argument
    new_root = Toplevel()
    new_root.minsize(width=300, height=300)
    var.set(-99)  # deselect by using value not associated with any RadioButtons
    for i in range(8):
        Radiobutton(new_root, text=str(i), variable=var, value=i).pack()

def main():
    root = Tk()
    root.minsize(width=400, height=250)
    root.var = IntVar()  # create it here to give access to it in the rest of your code
    CodeButton(root)
    root.mainloop()

main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接