[wxPython] messing with the event handler

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[wxPython] messing with the event handler

Ken Seehof-2
I'd like to find a way to skip all but the last in a sequence of mouse
move events.

The reason is that I have my own paint strategy (which is based on a
typical VR approach) that uses a backplane and a background layer to
only paint objects that are in motion.  The OnPaint handler itself
simply blits the backplane to the paint DC.  The idea is to get the
smoothest possible multiple object drag operation (i.e. maximize the
animation frame rate), so ideally I want to have a 1 to 1 ratio between
processed mouse events and paint events.

The problem I run into is that while processing a mouse move during a
drag, I sometimes get multiple extra mouse events queued up, so that I
have to process several events before a single paint, which is rather
redundant since I only care about the last mouse move.  The result is
very choppy because the continuous stream of mouse events leaves no time
for painting.

The simplest approach would be to peek at the next event.  If it's
another mouse move, I skip the current one, and repeat until I hit the
"last" mouse move event.  Unfortunately I don't know how to peek ahead
into the event queue in wxPython.

Any information or advice you have on event queue processing would be
helpful in finding the best strategy.

Thanks

- Ken



_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] messing with the event handler

Ken Seehof-2
I got it to work by saving the mouse state and processing in
OnIdle and after OnPaint.
I'm a little worried about portability, but time will tell....
Still, I'm curious about the following:

1. How do you post custom events?
2. Is it legal and portable to paint outside of OnPaint?

NiWidgets are coming soon....

Ken Seehof wrote:

> I'd like to find a way to skip all but the last in a sequence of mouse
> move events.
>
> The reason is that I have my own paint strategy (which is based on a
> typical VR approach) that uses a backplane and a background layer to
> only paint objects that are in motion.  The OnPaint handler itself
> simply blits the backplane to the paint DC.  The idea is to get the
> smoothest possible multiple object drag operation (i.e. maximize the
> animation frame rate), so ideally I want to have a 1 to 1 ratio between
> processed mouse events and paint events.
>
> The problem I run into is that while processing a mouse move during a
> drag, I sometimes get multiple extra mouse events queued up, so that I
> have to process several events before a single paint, which is rather
> redundant since I only care about the last mouse move.  The result is
> very choppy because the continuous stream of mouse events leaves no time
> for painting.
>
> The simplest approach would be to peek at the next event.  If it's
> another mouse move, I skip the current one, and repeat until I hit the
> "last" mouse move event.  Unfortunately I don't know how to peek ahead
> into the event queue in wxPython.
>
> Any information or advice you have on event queue processing would be
> helpful in finding the best strategy.
>
> Thanks
>
> - Ken
>
> _______________________________________________
> wxPython-users maillist  -  [hidden email]
> http://starship.python.net/mailman/listinfo/wxpython-users




_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] messing with the event handler

Bill Eldridge-2

Does this do what you want?

    def OnMotion(self,event):
        if event.Dragging() and event.LeftIsDown():
                self.select = 1
                self.drag=1

    def OnLeftUp(self,event):
        if self.drag:
                self.drag=0
                {any other processing}
                self.Refresh(false,x,y,xdim,ydim)
                event.Skip()

You could trap and ignore other mouse events
this way as well.

Ken Seehof wrote:

>
> I got it to work by saving the mouse state and processing in
> OnIdle and after OnPaint.
> I'm a little worried about portability, but time will tell....
> Still, I'm curious about the following:
>
> 1. How do you post custom events?
> 2. Is it legal and portable to paint outside of OnPaint?
>
> NiWidgets are coming soon....
>
> Ken Seehof wrote:
>
> > I'd like to find a way to skip all but the last in a sequence of mouse
> > move events.
> >
> > The reason is that I have my own paint strategy (which is based on a
> > typical VR approach) that uses a backplane and a background layer to
> > only paint objects that are in motion.  The OnPaint handler itself
> > simply blits the backplane to the paint DC.  The idea is to get the
> > smoothest possible multiple object drag operation (i.e. maximize the
> > animation frame rate), so ideally I want to have a 1 to 1 ratio between
> > processed mouse events and paint events.
> >
> > The problem I run into is that while processing a mouse move during a
> > drag, I sometimes get multiple extra mouse events queued up, so that I
> > have to process several events before a single paint, which is rather
> > redundant since I only care about the last mouse move.  The result is
> > very choppy because the continuous stream of mouse events leaves no time
> > for painting.
> >
> > The simplest approach would be to peek at the next event.  If it's
> > another mouse move, I skip the current one, and repeat until I hit the
> > "last" mouse move event.  Unfortunately I don't know how to peek ahead
> > into the event queue in wxPython.
> >
> > Any information or advice you have on event queue processing would be
> > helpful in finding the best strategy.
> >
> > Thanks
> >
> > - Ken
> >
> > _______________________________________________
> > wxPython-users maillist  -  [hidden email]
> > http://starship.python.net/mailman/listinfo/wxpython-users
>
> _______________________________________________
> wxPython-users maillist  -  [hidden email]
> http://starship.python.net/mailman/listinfo/wxpython-users

--
Bill Eldridge
Radio Free Asia
[hidden email]

_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] messing with the event handler

Joshua Judson Rosen-2
In reply to this post by Ken Seehof-2
>The simplest approach would be to peek at the next event.  If it's
>another mouse move, I skip the current one, and repeat until I hit the
>"last" mouse move event.  Unfortunately I don't know how to peek ahead
>into the event queue in wxPython.

My thought would be not to peek -ahead-, but to look -back-, by thought-process being:

you need to define what `last' means;
The -real- last mouse event will have no mouse events after it (until the Window is close), so, `last' meaning `the last in a sequence before a lull' is probably more useful.
You need to define what a `lull' is, like `a perioud without a mouse event being sent, which lasts for more than 1 second'.
So, you need a way to detect these `lulls':

Movement is displacement over time, and, since we're digital, we've discrete movements in a sequence spread over time, and we can see how often they're occuring by checking the time between two different events--preferably the two closest to `now'.

We can do comparisons with either of:
+`now' and the point immediately before it
+`now' and the point immediately after it

Looking back is usually easier than looking forward, so we do the first comparison:

Every time you get a mouse event, you check to see if one just happened, within the last second.

Having a variable which stores the time of the last mouse event would work.
Something like:

def process_movement(event, *args):
    curtime = time.time()
    if curtime - prevtime > threshold: #threshold being a number in seconds, ie: 1.
        event.Skip() #If we've hit a lull, just Skip.
    else: #we're not in a lull yet--the mouse is moving more than 1 event per threshold-unit
        ... dosomething...
    prevtime = curtime



_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] messing with the event handler

Ken Seehof-2
Clever, but the whole point is to maximize smoothness (and responsiveness) of a drag operation.  Anything involving testing for a delay will cause lag in the final result.  I certainly don't want to wait for a lull before painting; I want continuous
updates while the mouse is in motion.  So what I was looking for was the last mouse event up to time t, even while the mouse is being moved, (not the last position before a lull), and this move must be processed immediately (which will cause a paint).
My enemy is the buildup of mouse events on the queue during a paint operation, so I needed a way to "flush" the queue.

Here's the solution I ended up with:

OnMouseMove records the last mouse move event, which is processed and the end of the next paint, or at the next OnIdle.  So during a drag there is one paint for every processed mouse move with the maximum possible frame rate (which is defined by the
time it takes for the paint plus the time it takes to process one mouse event). The result is a continuous stream of alternating paints and mouse updates which is exactly what I want to get a nice smooth drag.

Joshua Rosen wrote:

> >The simplest approach would be to peek at the next event.  If it's
> >another mouse move, I skip the current one, and repeat until I hit the
> >"last" mouse move event.  Unfortunately I don't know how to peek ahead
> >into the event queue in wxPython.
>
> My thought would be not to peek -ahead-, but to look -back-, by thought-process being:
>
> you need to define what `last' means;
> The -real- last mouse event will have no mouse events after it (until the Window is close), so, `last' meaning `the last in a sequence before a lull' is probably more useful.
> You need to define what a `lull' is, like `a perioud without a mouse event being sent, which lasts for more than 1 second'.
> So, you need a way to detect these `lulls':
>
> Movement is displacement over time, and, since we're digital, we've discrete movements in a sequence spread over time, and we can see how often they're occuring by checking the time between two different events--preferably the two closest to `now'.
>
> We can do comparisons with either of:
> +`now' and the point immediately before it
> +`now' and the point immediately after it
>
> Looking back is usually easier than looking forward, so we do the first comparison:
>
> Every time you get a mouse event, you check to see if one just happened, within the last second.
>
> Having a variable which stores the time of the last mouse event would work.
> Something like:
>
> def process_movement(event, *args):
>     curtime = time.time()
>     if curtime - prevtime > threshold: #threshold being a number in seconds, ie: 1.
>         event.Skip() #If we've hit a lull, just Skip.
>     else: #we're not in a lull yet--the mouse is moving more than 1 event per threshold-unit
>         ... dosomething...
>     prevtime = curtime




_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users