Delaying events?

I have a panel with some TextControls, many of which have an event bound to call a routine which will update yet other controls. I do the initial load of the controls in a fairly tight loop, but the events are actually being hit while my loop is running. (I didn't think it could do that.) This causes erroneous results since some of the controls don't yet have values.

Is there some way to hold off the events until I have everything loaded and ready for them? Don't want to lose the events, juts hold them in queue. I tried panel.Freeze() and panel.SetEvtHandlerDisabled() to no effect.

Ideas?

Thanks,
Michael

What events? Maybe using ChangeValue instead of SetValue to load initial values?

Werner

···

On 10/31/2011 04:09 PM, Michael Hipp wrote:

I have a panel with some TextControls, many of which have an event bound to call a routine which will update yet other controls. I do the initial load of the controls in a fairly tight loop, but the events are actually being hit while my loop is running. (I didn't think it could do that.) This causes erroneous results since some of the controls don't yet have values.

Is there some way to hold off the events until I have everything loaded and ready for them? Don't want to lose the events, juts hold them in queue. I tried panel.Freeze() and panel.SetEvtHandlerDisabled() to no effect.

Sorry, I somehow thought that was obvious; I'm bind an event for when the text control value changes:

   self.textctrl.Bind(wx.EVT_TEXT, self._on_numbers_changed)

I had never come across ChangeValue() before, I'll give that a try for the initial loading. Thanks.

Michael

···

On 10/31/2011 10:33 AM, werner wrote:

On 10/31/2011 04:09 PM, Michael Hipp wrote:

I have a panel with some TextControls, many of which have an event
bound to call a routine which will update yet other controls. I do the
initial load of the controls in a fairly tight loop, but the events
are actually being hit while my loop is running. (I didn't think it
could do that.) This causes erroneous results since some of the
controls don't yet have values.

Is there some way to hold off the events until I have everything
loaded and ready for them? Don't want to lose the events, juts hold
them in queue. I tried panel.Freeze() and
panel.SetEvtHandlerDisabled() to no effect.

What events? Maybe using ChangeValue instead of SetValue to load initial
values?

That will work, I use it all the time for the wx.lib.masked when
loading values programmatically, see also:

wx.EVT_TEXT(id, func)

Respond to a wx.wxEVT_COMMAND_TEXT_UPDATED
event, generated when the text changes. Notice that this event will
be sent when the text controls contents changes - whether this is
due to user input or comes from the program itself (for example, if
SetValue()
is called); see ChangeValue() for a function which
does not send this event.

Werner
···

On 10/31/2011 04:41 PM, Michael Hipp wrote:

  On

10/31/2011 10:33 AM, werner wrote:

    On 10/31/2011 04:09 PM, Michael Hipp > > wrote:
      I have a panel with some TextControls,

many of which have an event

      bound to call a routine which will update yet other controls.

I do the

      initial load of the controls in a fairly tight loop, but the

events

      are actually being hit while my loop is running. (I didn't

think it

      could do that.) This causes erroneous results since some of

the

      controls don't yet have values.




      Is there some way to hold off the events until I have

everything

      loaded and ready for them? Don't want to lose the events, juts

hold

      them in queue. I tried panel.Freeze() and


      panel.SetEvtHandlerDisabled() to no effect.
    What events? Maybe using ChangeValue instead of SetValue to load

initial

    values?
  Sorry, I somehow thought that was obvious; I'm bind an event for

when the text control value changes:

    self.textctrl.Bind(wx.EVT_TEXT, self._on_numbers_changed)




  I had never come across ChangeValue() before, I'll give that a try

for the initial loading.

I have a panel with some TextControls, many of which have an event bound to
call a routine which will update yet other controls. I do the initial load
of the controls in a fairly tight loop, but the events are actually being
hit while my loop is running. (I didn't think it could do that.) This causes
erroneous results since some of the controls don't yet have values.

Is there some way to hold off the events until I have everything loaded and
ready for them?

Yes, a couple of ways. You could do your binds to your widgets after
your forms are finished:

def __init__(self, *args, **kwargs):
    super(MyFrame, self).__init__(*args, **kwargs)
    # do unbinds
    # create controls
    # layout/arrange controls
    # pre-fill controls with default data
    # (re)do binds
    # show() stuff

You could check a flag in your handlers:
    def OnUpdate(self, event):
        obj = event.GetEventObject()
       someWidget = GetCorrectWidget()
        if someWidget.initialized: # <- set after where widget initialized
            obj.SetValue( ProcessIt( someWidget.GetValue() ) )
        # depending on event type:
        if useCaseAppropiate:
            event.Skip()

You could add attributes to the events themselves at the control's
personal event handlers and resend the event with PostEvent() or
wx.CallAfter(wx.PostEvent) or the new method PostWindowEvent.

http://wiki.wxpython.org/CustomEventClasses

You could move towards an Observer pattern which uses a notify() like interface
http://code.activestate.com/recipes/131499-observer-pattern/
http://www.wxpython.org/docs/api/wx.NotifyEvent-class.html

Don't want to lose the events, juts hold them in queue.

import Queue
def OnSomeEvent(self, event):
    evtQueue = Queue.Queue()
    evtQueue.put(event)
    # then no event.Skip()

Then later wx.ProcessEvent( evtQueue.get() ) or AddPendingEvent( evtQueue.get)

I tried panel.Freeze() and panel.SetEvtHandlerDisabled() to no effect.

panel.Freeze() allows visual events to be done on a buffer in the
background so when you thaw you instantly see all the visual changes
all in one shot instead of visually incrementally - to reduce flicker.

Disabling the panel's Event handler appears to allow the event
dispatcher to continue to search for active event handlers up the
chain, that being the frame or other parent widgets or event handlers
that are pushed onto the panel, I imagine disabling the panel's event
handler does not disable the control's event handlers, not the panels
parents, which for some events goes all the way up to your App object.

Ideas?

Don't know if that's the right way; I think there is a way to delay an
event; but I'm not able to find anything on it.

···

On Mon, Oct 31, 2011 at 11:09 AM, Michael Hipp <michael@redmule.com> wrote:

Thanks,
Michael

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Don't want to lose the events, juts hold them in queue.

import Queue
def OnSomeEvent(self, event):
     evtQueue = Queue.Queue()
     evtQueue.put(event)
     # then no event.Skip()

Then later wx.ProcessEvent( evtQueue.get() ) or AddPendingEvent( evtQueue.get)

This will probably have problems. The C++ part of the event objects will normally be destroyed when control returns from the event handler. You could try putting clones in the queue though...

I tried panel.Freeze() and panel.SetEvtHandlerDisabled() to no effect.

panel.Freeze() allows visual events to be done on a buffer in the
background so when you thaw you instantly see all the visual changes
all in one shot instead of visually incrementally - to reduce flicker.

Not exactly. Freeze basically just suspends the sending of paint events until the window is thawed. Buffering is done separately. You are correct that the intent is to help reduce flicker (by eliminating some of the redraws) though.

···

On 10/31/11 8:57 AM, Dev Player wrote:

On Mon, Oct 31, 2011 at 11:09 AM, Michael Hipp<michael@redmule.com> wrote:

--
Robin Dunn
Software Craftsman