1

wxPython 和(分组的)单选按钮问题:

我有三个单选按钮绑定在一个组中,我看到这让我可以选择单选按钮 A、B 或 C,其中一个总是被选中——我很欣赏这是 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通过创建自定义来覆盖选择句柄的方式wx.RadioButton。以下是我使用这种方法发现的一些问题:

  1. wx.EVT_RADIOBUTTON仅在系统已更改单选按钮的值后才被捕获,因此我实际上无法覆盖行为
  2. 按钮在不同时间捕获wx.EVT_RADIOBUTTONid指定否时),因此无法预测系统是否有进一步的更改排队,这可能会覆盖您对按钮值所做的任何更改。
  3. wx.EVT_RADIOBUTTON如果已选择单选按钮,则不会生成
  4. wxPython 只有wx.EVT_LEFT_DOWNwx.EVT_LEFT_UP事件,两者都没有完全描述单选按钮如何知道它已被点击

然后我转向自定义wx.RadioBox,但我很快意识到没有方法可以完全取消选择单选框内的按钮,这意味着它也不是一个可接受的选择。

我想您可以编写某种wx.Panel包含多个wx.CheckBox对象的自定义,并尝试强制一次最多选择一个框,但是您再次遇到问题,这不是用户期望复选框的工作方式。我以前见过这种行为,但每次它都让我觉得很奇怪,我不能推荐它。此外,它还需要相当大的努力来发展。

我能找到的最接近您所要求的解决方案是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 回答