WxPython: desencadena un evento de checkbox mientras configura su valor en el código

Considere la siguiente pieza de código:

import wx class MyFrame(wx.Frame): def __init__(self, *args, **kwds): wx.Frame.__init__(self, *args, **kwds) self.cb1 = wx.CheckBox(self, -1, "CheckBox 1") self.cb2 = wx.CheckBox(self, -1, "CheckBox 2") self.cb3 = wx.CheckBox(self, -1, "CheckBox 3") sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.cb1, 0, wx.ADJUST_MINSIZE, 0) sizer.Add(self.cb2, 0, wx.ADJUST_MINSIZE, 0) sizer.Add(self.cb3, 0, wx.ADJUST_MINSIZE, 0) self.SetSizer(sizer) self.Layout() self.Bind(wx.EVT_CHECKBOX, self.OnCb1, self.cb1) self.Bind(wx.EVT_CHECKBOX, self.OnCb2, self.cb2) def OnCb1(self, evt): self.cb2.SetValue(evt.IsChecked()) def OnCb2(self, evt): self.cb3.SetValue(evt.IsChecked()) if __name__ == "__main__": app = wx.PySimpleApp(0) frame = MyFrame(None, -1, "") app.SetTopWindow(frame) frame.Show() app.MainLoop() 

Aquí tengo 3 casillas de verificación unidas entre sí, por lo que cb2 se comprueba cuando cb1 hace y cb3 se comprueba cuando cb2 hace. Sin embargo, cuando configuro el valor de cb2 en la rutina OnCb1 , el evento de la checkbox cb2 no se activa, y la checkbox cb3 permanece sin marcar. Así que me gustaría encontrar una manera de activar de alguna cb2 evento cb2 manualmente para marcar las 3 casillas a la vez cuando solo se verifica cb1 . Estaría muy agradecido si alguien me da una pista.

Utilice wx.PostEvent … así:

 class launcherWindow(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent=None, title='New Window') #now add the main body, start with a panel panel = wx.Panel(self) #instantiate a new dropdown self.productDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY) #get the products and product subtypes self.productDict = self.getProductsAndSubtypes() #setup subtypes first, just in case, since onProductSelection will reference this self.productSubtypeDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY) #add products for product in self.productDict.keys(): self.productDropDown.Append(product) #bind selection event self.productDropDown.Bind(wx.EVT_COMBOBOX, self.onProductSelection) #set default selection self.productDropDown.SetSelection(0) #pretend that we clicked the product selection, so it's event gets called wx.PostEvent(self.productDropDown, wx.CommandEvent(wx.wxEVT_COMMAND_COMBOBOX_SELECTED)) #now add the dropdown to a sizer, set the sizer for the panel, fit the panel, etc... def onProductSelection(self, event): productSelected = self.productDropDown.GetStringSelection() productSubtypes = self.productDict[productSelected] #clear any existing product subtypes, since each product may have different ones self.productSubtypeDropDown.Clear() for productSubtype in productSubtypes: self.productSubtypeDropDown.Append(productSubtype) #select the first item by default self.productSubtypeDropDown.SetSelection(0) 

No pude adoptar el código de nmz787 directamente, y tuve que hackear un poco, pero finalmente lo conseguí trabajando para

  • cambiando el estado de una checkbox y
  • haciendo que la casilla reciba el evento,

Al igual que si el usuario hizo clic en él.

Pensé que publicaría mi código en caso de que otros se atascaran intentando que esto también funcionara. Como solo dependía de la checkbox y no del control que lo llamaba, lo consideré como una función independiente de “nivel superior”, no como un método en ninguna clase.

 def toggleCheckBox(cb): evt = wx.CommandEvent(commandType=wx.EVT_CHECKBOX.typeId) evt.SetEventObject(cb) cb.SetValue( not cb.GetValue()) wx.PostEvent(cb, evt) 

No tengo idea de por qué el constructor CommandEvent requirió una palabra clave, o si hay una manera más sensata y sólida de obtener el ID de tipo requerido, pero esto funcionó para mí.

No tengo experiencia con wxPython, por lo que no puedo darle un ejemplo específico, pero sí sé que establecer el valor mediante progtwigción no activará eventos de comando para los widgets. Supongo que tendrá que publicar manualmente el evento para cb2 después de establecer su valor. Puede revisar una pregunta similar aquí: wxPython: llamar un evento manualmente

Lo que podría sugerir es subclasificar el wx.CheckBox y crear un SetValueWithEvent() o un método similar que llamará SetValue, y publicar un wx. EVT_CHECKBOX Evento wx. EVT_CHECKBOX .

PyQt tiene situaciones similares en las que las señales pueden o no emitirse cuando se configuran valores en un widget mediante progtwigción. A veces le darán más de una señal que puede escuchar para adaptarse de cualquier manera. Desafortunadamente, debido a mi limitada exposición a los ejemplos de wxPython, creo que es mucho más primitivo y un poco menos pythonico. Así que parece que tienes que hacer las cosas un poco más a menudo.