Tkinter 单选按钮初始化错误

10 投票
6 回答
11890 浏览
提问于 2025-04-16 12:15

如果我把单选按钮放在一个函数里并绘制它们,第一次绘制的时候,你无法把鼠标悬停在上面,否则它们看起来就像全都被选中了。

把相同的代码放在函数外面就不会出现这种情况。

from Tkinter import *

def App(master):
    v = StringVar()
    v.set('python') # initialize
    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()
    runtimeFrame = Frame(master, relief=GROOVE,  borderwidth = 3)
    runtimeFrame.pack(fill = X, pady = 5, padx = 5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron = 1 )
        b.pack(side = LEFT)


if __name__ == '__main__':
    master = Tk()

    App(master)

    #The following code chunk is the same as that in App()
    #------------------------
    v = StringVar()
    v.set('python') # initialize
    lable1 = Label(master, text=' hovering over below radio buttons will cause them to Not look selected as expected')
    lable1.pack()
    runtimeFrame = Frame(master, relief=GROOVE,  borderwidth = 3)
    runtimeFrame.pack(fill = X, pady = 5, padx = 5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron = 1 )
        b.pack(side = LEFT)
    #------------------------

    mainloop() 

一旦你做了选择,这种情况就不会再发生了。 我是不是做错了什么?有没有什么解决办法,因为我的代码必须放在一个函数里!

这是我在Tkinter中发现的第二个基础性错误。有没有更好的工具可以用来做Python的图形界面开发?

顺便说一下:我用的是python 2.7

6 个回答

2

我知道这已经过去很久了,但我试过这里提到的很多方法,都没能解决我的问题。对我有效的办法就是简单地“重写”鼠标移动事件的处理函数。这不是一个完美的解决方案,因为我在终端上打印了一些奇怪的东西,但在我这个特定的情况下,这并不是问题。

server_name = IntVar()
server_name.set(1)
server_name_rb_1 = Radiobutton(container_3, text="Server", variable=server_name, value=1)
server_name_rb_1.select()
server_name_rb_1.pack()
server_name_rb_2 = Radiobutton(container_3, text="Local", variable=server_name, value=2)
server_name_rb_2.deselect()
server_name_rb_2.pack()

server_name_rb_2.bind('<Motion>',lambda e: print(str(server_name.get())) )

附注:你不需要重写所有的函数,只重写其中一个就足够了。

4

试试这个,这对我有效。

v = 0  # this is global variable

def some_function():
    global v
    v = IntVar()
    v.set(0)


    rb1 = Radiobutton (parent, variable = v, value = 0)
    rb1.pack()
    rb2 = Radiobutton (parent, variable = v, value = 1)
    rb2.pack()

先做出你的单选按钮,然后你就能得到应该有的单选按钮效果。

14

你存储变量对象(在你的例子中是StringVar和v)的地方必须保持有效,这样就不会出现奇怪的行为。我猜我们看到这种情况是因为v超出了作用域,出了点问题。除了使用全局变量,我想不出其他方法可以在函数中做到这一点。

有问题的代码:

from Tkinter import *

def App(master):
    v = StringVar()
    v.set('python')

    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()

    runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
    runtimeFrame.pack(fill=X, pady=5, padx=5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron=1)
        b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    App(master)
    mainloop()

修复示例:

from Tkinter import *

def App(master, radio_var):
    radio_var.set('python')

    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()

    runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
    runtimeFrame.pack(fill=X, pady=5, padx=5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=radio_var, value=mode, indicatoron=1)
        b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    radio_var = StringVar()
    App(master, radio_var)
    mainloop()

如果你有多个变量需要保持有效,可以考虑传入一个变量的列表或字典。

另外,如果“必须在函数中”是作业要求,可以考虑把代码放在一个类里。我不是tk的专家,但这似乎是组织代码的更好方式。

修复示例2:

    from Tkinter import *

class App(object):
    def __init__(self, master):
        self.radio_var = StringVar()
        self.radio_var.set('python')

        lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
        lable1.pack()

        runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
        runtimeFrame.pack(fill=X, pady=5, padx=5)
        for mode in ['java', 'python', 'jython']:
            b = Radiobutton(runtimeFrame, text=mode, variable=self.radio_var, value=mode, indicatoron=1)
            b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    app = App(master)
    mainloop()

注意到这里有一个小变化

app = App(master)

这样做是为了防止App实例被过早清理掉。这样会导致self.radio_var超出作用域,我们又回到了最初的问题。

撰写回答