为什么使用 StringVar 而不是 IntVar 时 Tkinter 的单选按钮都开始选中?

2022-01-21 00:00:00 python python-3.x tkinter tk radio-button

问题描述

这里是一些示例代码,它创建了 4 个 Radiobutton,其中 2 个使用 int,2 个使用 str:

Here is some example code that creates 4 Radiobuttons, 2 using int and 2 using str:

from tkinter import *

class test:
    def __init__(self):
        wind = Tk()
        frame1 = Frame(wind)
        frame1.pack()
        self.v1 = IntVar()
        self.v2 = StringVar()

        int1 = Radiobutton(frame1, text = 'int1', variable = self.v1, value = 1,
                           command = self.ipress)
        int2 = Radiobutton(frame1, text = 'int2', variable = self.v1, value = 2,
                           command = self.ipress)

        str1 = Radiobutton(frame1, text = 'str1', variable = self.v2, value = '1',
                           command = self.spress)
        str2 = Radiobutton(frame1, text = 'str2', variable = self.v2, value = '2',
                           command = self.spress)

        int1.grid(row = 1, column = 1)
        int2.grid(row = 1, column = 2)

        str1.grid(row = 2, column = 1)
        str2.grid(row = 2, column = 2)

        str1.deselect() #this didn't fix it
        str2.deselect()

    def ipress(self):
        print('int'+str(self.v1.get()))
    def spress(self):
        print('str'+self.v2.get())

test()

运行后,我有一个如下所示的框:

After running this I have a box that look like this:

出于某种原因,str 开始被选中,而 int 则没有.是否有一个原因?有什么解决办法吗?我知道我可以通过使用数值然后将它们转换为字符串来解决它,但我想先了解为什么会发生这种情况.

For some reason the str ones start selected while the int ones do not. Is there a reason for this? Is there any fix for it? I know I could work around it by just using number values and then converting them to strings but I'd like to understand why this is happening first.

如果这很重要,我正在使用 Windows 10.

I am using Windows 10 if that matters.

澄清一下,这些按钮在被点击后仍然可以正常工作.

for clarification, the buttons still work properly after they have been clicked on.


解决方案

在第二组单选按钮的情况下,它们以三态模式"呈现.

In the case of the second set of radiobuttons, they are being rendered in "tri-state mode".

根据官方文档1:

如果变量的值与 tristateValue 匹配,则单选按钮是使用三态模式绘制的.该模式用于表示混合值或多个值.

If the variable's value matches the tristateValue, then the radiobutton is drawn using the tri-state mode. This mode is used to indicate mixed or multiple values.

说明

tristatevalue 的默认值为空字符串,StringVar 的默认值为空字符串.对于您的第二组单选按钮,变量值和 tristatevalue 都是相同的,因此您看到的是三态模式".

Explanation

The default for tristatevalue is the empty string, and the default value for a StringVar is the empty string. For your second set of radiobuttons both the variable value and the tristatevalue are the same so you are seeing the "tri-state mode".

IntVar 的情况下,变量的默认值为零.tristatevalue 仍然是空字符串.这两个是不同的,所以小部件不会出现在三态模式"中.

In the case of the IntVar, the default value of the variable is zero. The tristatevalue is still the empty string. Those two are different so the widget does not appear in "tri-state mode".

为了证明这一点,请将第一组单选按钮的 tristatevalue 设置为零,使其与关联变量的默认值匹配,您将看到它们的外观发生变化以匹配第二组.

To prove this, set tristatevalue to zero for the first set of radiobuttons so that it matches the default value of the associated variable and you will see that their appearance changes to match the second set.

int1 = Radiobutton(..., tristatevalue=0)
int2 = Radiobutton(..., tristatevalue=0)

同样,您可以将第二组的 tristatevalue 设置为默认值以外的其他值,以便它们看起来像第一组:

Likewise, you could set the tristatevalue of the second set to something other than the default value so that they will look like the first set:

str1 = Radiobutton(..., tristatevalue="x")
str2 = Radiobutton(..., tristatevalue="x")

解决方案

单选按钮的最佳做法是始终确保默认值对应于单选按钮值之一,除非您确实需要三态模式".

Solution

The best practice with radiobuttons is to always make sure the default value corresponds to one of the radiobutton values, unless you truly do want "tri-state mode".

在您的情况下,您应该将变量初始化为单选按钮之一的值:

In your case, you should initialize the variables to the value of one of the radiobuttons:

self.v1 = IntVar(value=1)
self.v2 = StringVar(value="1")

... 或者在你创建它们之后,通过 set:

... or after you create them, via set:

self.v1.set(1)
self.v2.set("1")

<小时>

1 链接指向 tcl/tk 手册页.Tkinter 只是 tcl/tk 的一个薄包装,这个文档是小部件行为方式的明确答案.


1 the link goes to the tcl/tk man pages. Tkinter is just a thin wrapper around tcl/tk, and this documentation is the definitive answer to how the widgets behave.

相关文章