2013-02-13 5 views
1

WxPython и (сгруппированный) радио-кнопка вопрос:WxPython, радио кнопка выбор/снятие и wx.RB_GROUP

У меня есть три переключателя, которые связаны в группе, я вижу, что это дает мне выбор радио-кнопок A, B или C, где всегда выбирается - я понимаю, что это характер стиля wx.RB_GROUP;

Можно ли отменить выбор всех кнопок, как в A = B = C = False, только нажав на переключатели? У меня упорядоченный код (ниже), где кнопка Reset выполняет эту функцию, но в идеале я просто хотел бы отменить выбор в графическом интерфейсе.

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

Насколько я могу судить, это не поддерживается в wxPython. Кроме того, это не ожидаемое поведение переключателей в любом пользовательском интерфейсе, поэтому я впервые подумал, что дизайн вашего интерфейса неверен. Рассматривали ли вы добавление дополнительного переключателя «Нет», который логически не эквивалентен ни одному из ваших переключателей? Почему нет?

Однако я попытался взломать решение, но безуспешно. На самом деле, учитывая трудности, с которыми я столкнулся, я очень подозреваю, что даже если это есть, можно запрограммировать это поведение, вам все же лучше найти альтернативу.

Моя первая идея состояла в том, чтобы переписать как wx.RadioButton дескрипторы выбираются путем создания пользовательского wx.RadioButton. Вот некоторые из проблем, которые я нашел с этим подходом:

  1. wx.EVT_RADIOBUTTON только пойманной после система уже изменила значение кнопки радио, так что я не могу на самом деле перезаписать поведение
  2. Кнопки поймать wx.EVT_RADIOBUTTON (когда не указано id) в разное время, поэтому невозможно предсказать, имеет ли система дальнейшие изменения очереди, которые могут переписать любые изменения, внесенные вами в значение кнопки.
  3. wx.EVT_RADIOBUTTON не генерируется, если радио-кнопка выбрана
  4. WxPython только wx.EVT_LEFT_DOWN и wx.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 с меткой «None» является лучшим решением, поскольку она требует минимальных усилий, и это соответствует ожиданиям пользователей о том, как радио кнопка должна работать (что делает его более понятным) ,

+0

Большое спасибо, что нашли время, чтобы посмотреть на что, пользовательский радиокнопка выполняет ту же работу, что и мой сброс, как указано: def onRst (self, event): self.radio1.SetValue (0) –

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())