1

wxPythonと(グループ化された)ラジオボタンの問題:

グループにバインドされた3つのラジオボタンがあります。これにより、ラジオボタンA、B、またはCを選択でき、常に1つが選択されます。これがwx.RB_GROUPスタイルの性質であることに感謝します。

ラジオボタンのみをクリックして、A = B = C = Falseのようにすべてのボタンの選択を解除することはできますか?リセットボタンがこの機能を実行するコード(下記)を合理化しましたが、理想的にはGUIで選択を解除したいと思います。

import wx
class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Tutorial", size=(300,250))
        panel = wx.Panel(self, wx.ID_ANY)
        self.radio1 = wx.RadioButton(panel, label="A", pos=(20,40), style=wx.RB_GROUP)
        self.radio2 = wx.RadioButton(panel, label="B", pos=(20,70))
        self.radio3 = wx.RadioButton(panel, label="C", pos=(20,100))

        btn = wx.Button(panel, label="Check", pos=(20,140))
        rst = wx.Button(panel, label="Reset", pos=(20,170))
        btn.Bind(wx.EVT_BUTTON, self.onBtn)
        rst.Bind(wx.EVT_BUTTON, self.onRst)

    def onBtn(self, event):
        print "A = ", self.radio1.GetValue()
        print "B = ", self.radio2.GetValue()
        print "C = ", self.radio3.GetValue()
        print "\n\n"

    def onRst(self, event):
        self.radio1.SetValue( 0 )
        self.radio2.SetValue( 0 )
        self.radio3.SetValue( 0 )

if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm().Show()
    app.MainLoop()
4

2 に答える 2

4

私が知る限り、これは wxPython でネイティブにサポートされていません。さらに、これは任意の UI のラジオ ボタンの予想される動作ではないため、最初に考えたのは、インターフェイスの設計が正しくないということです。ラジオボタンが選択されていないことと論理的に同等の「なし」ラジオボタンをさらに追加することを検討しましたか? なぜだめですか?

ただし、解決策をハックしようとしましたが、成功しませんでした。実際、私が直面した困難を考えると、この動作をプログラムすること可能であったとしても、別の方法を見つけたほうがよいのではないかと強く思います。

wx.RadioButton私の最初のアイデアは、 custom を作成してハンドルの選択方法を上書きすることでしたwx.RadioButton。このアプローチで私が見つけた問題のいくつかを次に示します。

  1. wx.EVT_RADIOBUTTONシステムがラジオボタンの値をすでに変更したにのみキャッチされるため、実際に動作を上書きすることはできません
  2. wx.EVT_RADIOBUTTONボタンはさまざまなタイミングで(noが指定されている場合)キャッチidするため、ボタンの値に加えた変更を上書きする可能性がある追加の変更がシステムにキューに入れられているかどうかを予測することは不可能です。
  3. wx.EVT_RADIOBUTTONラジオボタンがすでに選択されている場合は生成されません
  4. wx.EVT_LEFT_DOWNwxPython にはとイベントしかありwx.EVT_LEFT_UPません。どちらも、ラジオ ボタンがクリックされたことをどのように認識しているかを完全には説明していません。

次にカスタムに移りましたwx.RadioBoxが、ラジオ ボックス内のボタンを完全に選択解除する方法がないことにすぐに気付きました。つまり、これも受け入れられる選択ではありません。

wx.Panel複数のオブジェクトを含むある種のカスタムを作成wx.CheckBoxし、一度に最大 1 つのボックスのみが選択されるように強制しようとすることができると思いますが、これはユーザーがチェック ボックスの動作を期待する方法ではないという問題に再び遭遇します。以前にこの動作を見たことがありますが、毎回奇妙に感じるのでお勧めできません。また、開発にはかなりの労力が必要です。

あなたが求めていることに私が見つけることができる最も近い解決策は、wx.RadioButtonダブルクリックすると選択を解除するカスタムです。ここでの問題は、ユーザーがラジオ ボタンの選択を解除するためにダブル クリックすることを期待していないことです。

class DeselectableRB(wx.RadioButton):
    def __init__(self, parent, label, pos=None, style=0):
        #do the default init
        wx.RadioButton.__init__(self, parent, label=label, pos=pos, style=style)

        #catch double clicks
        self.Bind(wx.EVT_LEFT_DCLICK, self.onDClick)

    def onDClick(self, event):
        self.SetValue(0)

ただし、「なし」というラベルの付いた追加機能が最善の解決策であると強く思いますwx.RadioButton。これは、最小限の労力で済み、ラジオ ボタンがどのように機能するかについてのユーザーの期待に適合する (より直感的になる) からです。

于 2013-02-14T00:26:56.053 に答える
1

これは、チェックボックスのように RadioButton の選択を解除するために機能します。

import wx
class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Tutorial", size=(300,250))
        panel = wx.Panel(self, wx.ID_ANY)
        self.radio1 = wx.RadioButton(panel, label="A", name='radio1', pos=(20,40), style=wx.RB_GROUP)
        self.radio2 = wx.RadioButton(panel, label="B", name='radio2', pos=(20,70))
        self.radio3 = wx.RadioButton(panel, label="C", name='radio3', pos=(20,100))

        self.radio1.Bind(wx.EVT_LEFT_DOWN, self.OnRB)
        self.radio2.Bind(wx.EVT_LEFT_DOWN, self.OnRB)
        self.radio3.Bind(wx.EVT_LEFT_DOWN, self.OnRB)


        btn = wx.Button(panel, label="Check", pos=(20,140))
        rst = wx.Button(panel, label="Reset", pos=(20,170))
        btn.Bind(wx.EVT_BUTTON, self.onBtn)
        rst.Bind(wx.EVT_BUTTON, self.onRst)

    def OnRB(self, event):
        event.GetEventObject().SetValue(not event.GetEventObject().GetValue())

    def onBtn(self, event):
        print "A = ", self.radio1.GetValue()
        print "B = ", self.radio2.GetValue()
        print "C = ", self.radio3.GetValue()
        print "\n\n"

    def onRst(self, event):
        self.radio1.SetValue( 0 )
        self.radio2.SetValue( 0 )
        self.radio3.SetValue( 0 )

if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm().Show()
    app.MainLoop()

コードに追加したのは次のとおりであることに注意してください。

    self.radio1.Bind(wx.EVT_LEFT_DOWN, self.OnRB)
    self.radio2.Bind(wx.EVT_LEFT_DOWN, self.OnRB)
    self.radio3.Bind(wx.EVT_LEFT_DOWN, self.OnRB)

def OnRB(self, event):
    event.GetEventObject().SetValue(not event.GetEventObject().GetValue())
于 2014-09-23T01:02:23.720 に答える