views:

101

answers:

2

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?

A: 

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
nosklo
Wait, do I need to actually create this **need X recalculated** flag or is it created for me?
cool-RR
See my edit above.
cool-RR
A: 

If you will post a event 1000 times you will receive it 1000 times, why would any event system group them, that would be a bug.

If you do not want to deal with all 1000 of them ignore them, also only you can decide how they should be grouped, if user changes something rapidly do you want to group those changes or respond to all events and have a better responsive UI?

In you case may be you should either

  1. group them with time e.g. handle events which come N msec apart
  2. Group the with value e.g. if last value is same as current value do nothing
  3. Set a flag is a object has been modified, you get event, you do something and reset flag, so next time on event check flag is something really has changed or not

But the bottom line is You have to decide how you respond to events.

Anurag Uniyal