Search code examples
pythoneventswxpythonwxwidgets

wxWidgets/wxPython: Do two identical events cause two handlings?


When there are two identical events in the event loop, will wxPython handle both of them, or will it call the handler only once for them both?

I mean, in my widget I want to have an event like EVT_NEED_TO_RECALCULATE_X. I want this event to be posted in all kinds of different circumstances that require x to be recalculated. However, even if there are two different reasons to recalculate x, only one recalculation needs to be done.

How do I do this?

EDIT:

I tried this code:

import wx

class Frame(wx.Frame):
    def __init__(self, parent=None):
        wx.Frame.__init__(self, parent)

        self.Bind(wx.EVT_COLOURPICKER_CHANGED, self.on_event)

        self.Centre()
        self.Show(True)

        self.i = 0

        self.event_all()

    def on_event(self, event):
        print self.i
        self.i += 1

    def event_all(self):
        for j in range(1000):
            event = wx.PyEvent()
            event.SetEventType(wx.EVT_COLOURPICKER_CHANGED.evtType[0])
            wx.PostEvent(self, event)


app = wx.App()
Frame(None)
app.MainLoop()

If the events do get grouped together, I'd expect it not to count all the way to 1000. But it does. Do they get grouped or not?


Solution

  • you're talking about three things

    • the event
    • the source of the event
    • the event handling

    The event is a single one (X needs to be recalculated). It has multiple sources. But it has only a single handler.

    So it should just work. You make it a single event, add a single handler to it, but signal/raise the event whenever you want - every time you raise the need X recalculated flag, the handler should run one time.


    EDIT:

    This line...

    event = wx.PyEvent()
    

    ...creates a new event. That means something happened, and must be reacted upon. If you create 1000 events, then sure, the event handler will be called 1000 times.

    The handler will be called once for each time the event happens, that is, once for each PyEvent instance that gets posted on the event queue.

    If you want to group them, one way is to not create a new PyEvent instance if one is pending:

    class Frame(wx.Frame):
        def __init__(self, parent=None):
            wx.Frame.__init__(self, parent)
            self.Bind(wx.EVT_COLOURPICKER_CHANGED, self.on_event)
            self.Centre()
            self.Show(True)
            self.i = 0
            self.recalculating = False
            self.event_all()
    
        def on_event(self, event):
            self.recalculating = False
            print self.i
            self.i += 1
    
        def event_all(self):
            for j in range(1000):
                if not self.recalculating:
                    event = wx.PyEvent()
                    event.SetEventType(wx.EVT_COLOURPICKER_CHANGED.evtType[0])
                    wx.PostEvent(self, event)
                    self.recalculating = True