web-dev-qa-db-ja.com

StringVarを使用しているのにIntVarを使用していないのに、Tkinterのラジオボタンがすべて選択され始めるのはなぜですか?

これは、4つのラジオボタンを作成するコード例です。2つはintを使用し、2つは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()

これを実行した後、私は次のようなボックスがあります:

何らかの理由で、strのものは選択され始めますが、intのものは選択されません。これには理由がありますか?修正はありますか? number valuseを使用して文字列に変換するだけで回避できることはわかっていますが、なぜこれが最初に発生するのかを理解したいと思います。

それが重要な場合、私はwindows 10を使用しています。

編集:明確化のために、ボタンはクリックされた後も正しく機能します。

助けてくれてありがとう

7
Whud

ラジオボタンの2番目のセットの場合、それらは「トライステートモード」でレンダリングされています。

公式ドキュメント によると1

変数の値がtristateValueと一致する場合、ラジオボタンはトライステートモードを使用して描画されます。このモードは、混合値または複数の値を示すために使用されます。

説明

tristatevalueのデフォルトは空の文字列であり、StringVarのデフォルト値は空の文字列です。 2番目のラジオボタンのセットでは、変数値とtristatevalueの両方が同じであるため、「トライステートモード」が表示されます。

IntVarの場合、変数のデフォルト値はゼロです。 tristatevalueはまだ空の文字列です。これら2つは異なるため、ウィジェットは「トライステートモード」では表示されません。

これを証明するには、ラジオボタンの最初のセットのtristatevalueをゼロに設定して、関連する変数のデフォルト値と一致させ、2番目のセットと一致するように外観が変化することを確認します。

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

同様に、2番目のセットのtristatevalueをデフォルト値以外に設定して、最初のセットのように見せることができます。

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

解決

ラジオボタンのベストプラクティスは、本当に「トライステートモード」が必要な場合を除いて、デフォルト値がラジオボタン値の1つに対応していることを常に確認することです。

あなたの場合、変数をラジオボタンの1つの値に初期化する必要があります。

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

...またはそれらを作成した後、setを介して:

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

1 リンクはtcl/tkのマニュアルページに移動します。 Tkinterはtcl/tkの単なる薄いラッパーであり、このドキュメントはウィジェットの動作に対する決定的な答えです。

11
Bryan Oakley