Consider the following piece of code:
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()
Here I have 3 checkboxes bound together, so cb2
gets checked when cb1
does and cb3
gets checked when cb2
does. However, when I set the value of cb2
in OnCb1
routine, the cb2
checkbox event is not triggered, and cb3
checkbox remains unchecked. So I'd like to find a way to trigger somehow cb2
event manually to check all 3 boxes at once when checking only cb1
. I'd be very grateful if anyone gives me a hint.
Use wx.PostEvent... like so:
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)
I couldn't adopt nmz787's code directly, and had to hack around a bit, but I finally got it working for
just as if the user clicked on it.
I thought I'd post my code in case others are stuck trying to get this to work too. Since it only depended on the checkbox and not on which control was calling it I factored it out as an independent "top-level" function, not as a method on any class.
def toggleCheckBox(cb):
evt = wx.CommandEvent(commandType=wx.EVT_CHECKBOX.typeId)
evt.SetEventObject(cb)
cb.SetValue( not cb.GetValue())
wx.PostEvent(cb, evt)
I have no idea why the CommandEvent constructor required a keyword, or if there's a more sensible, robust way to get the typeId required, but this worked for me.
I'm not experienced with wxPython so I can't give you a specific example, but I do know that setting the value programmatically will not trigger command events for the widgets. My assumption is that you will have to manually post the event for cb2 after you set its value. You can review a similar question here: wxPython: Calling an event manually
What I might suggest is to subclass the wx.CheckBox and create a SetValueWithEvent()
or similar method that will both call SetValue, and post a wx. EVT_CHECKBOX
wx. EVT_CHECKBOX
event.
PyQt has similar situations where signals may or may not be emitted when programmatically setting values on a widget. They will sometimes give you more than one signal that you can listen for to accomodate either way. Unfortunately, based only on my limited exposure to wxPython examples, I think its a lot more primitive, and a bit less pythonic. So you seem to have to do things yourself a little more often.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.