Re: wxPython fast and slow

2009-03-12 Thread David Bolen
iu2  writes:

> A question about CallAfter: As I understand, this function is intended
> to be used from within threads, where it queues the operation to be
> performed in the GUI queue.

I agree with the second half of the sentence but not the first.
CallAfter is intended to queue up a delayed call (via the GUI queue),
but it can be used anywhere you wish that behavior.  Yes, it's also
one of the very few functions that can be called from a thread other
than the GUI thread, but it works just as well from the GUI thread.

Or to quote its docstring:

Call the specified function after the current and pending event
handlers have been completed.  This is also good for making GUI
method calls from non-GUI threads.  Any extra positional or
keyword args are passed on to the callable when it is called.

> How does it work in this situation? Does it queue the opreation for
> some idle time or does it perform it right away?

You can actually see the source in _core.py in your wx installation.
It always executes via a wx.PostEvent call.

> And another question, if I may, I used to make tight loops in windows
> API, planting inside them a command that processes messages from the
> GUI queue and returns when no more messages exists. Something like
> this:
>
> loop {
>   operations
>   process_gui_messages
> }
>
> The loop ran quickly and the GUI remained responsive during the loop.
> I did it on window API using a function I defined similar to this one:

I don't think there's much difference in the above and doing your
operations during one of the events.  In both cases "operations" is
going to block any further event processing so cannot be lengthy or
the GUI will feel unresponsive.  "Lengthy" varies but I'd certainly
put it in the neighborhood of small fractions of a second.

Your original code took almost 2 seconds for the "operations" part
(before getting back to processing GUI messages through the main
loop), which certainly seems too long.

> void ProcessMessages()
> {
>   while (PeekMessage()) {
> TranslateMessage(..);
> DispatchMessage(..);
>   }
> }

Not quite positive, but if you're talking about implementing this as a
nested dispatch loop (e.g., called from within an existing event), you
can do that via wxYield.  Of course, as with any nested event loop
processing, you have to be aware of possible reentrancy issues.

> This technique is not good for long loops, where the user may activate
> other long GUI opreations during the tight loop and make a mess.
> But it carries out the job well where during the time of the loop the
> user may only access to certain features, such as pressing a button to
> cancel the operation, operating the menu to exit the program, etc.
> This scheme saves some state-machine code that is required when using
> event-based programming.

Maybe - for my own part, I'm not completely convinced and tend to far
prefer avoiding nested event loop dispatching.  There are some times
when it might be unavoidable, but I tend to find it indicative that I
might want to re-examine what I am doing.

It seems to me that as long as you have to keep the "operations" step
of your loop small enough, you have to be able to divide it up.  So
you'll need some state no matter what to be able to work through each
stage of the overall "operations" in between calls to process the GUI.

At that point, whether it's a local variable within the scope of the
looping code, or just some instance variables in the object handling
the event loop seems about the same amount of state management.

For example, in your original code you could probably consider the
generator and/or 'x' your local state.  But the current step in the
movement could just as easily be an instance variable.

> Does wxPython have something like ProcessMessages?

If you just mean a way to process pending messages wxYield may be
sufficient.

If you want to take over the primary dispatch loop for the application,
normally that has been handed off to wxWidgets via wxApp.MainLoop.  However,
I believe you can build your own main dispatch loop if you want, as there
are functions in wxApp like ProcessPendingEvents, Pending, Dispatch and
so on.  You may need to explicitly continue to support Idle events in
your own loop if desired.

If you need to get into more details, it's probably better dealt with
on the wxPython mailing list.

-- David
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-09 Thread iu2
On Mar 9, 4:18 am, David Bolen  wrote:
> iu2  writes:
>
> Then even a time.sleep() or plain loop isn't sufficient since each may
> have additional latencies depending on load.  You will probably need
> to query a system clock of some type to verify when your interval has
> passed.
>

> You might also try an idle event, implementing your own timer (using
> whatever call gives you the best resolution on your platform), and
> just ignoring idle events that occur more frequently than the timing
> you want.  Just remember to always request a new event.  You could do
> the same thing with CallAfter as well, just reschedule a new one if
> the current one is faster than your preferred interval.
>
> -- David

Thanks, I need to give it a try.

>
> Except that CallAfter passed control back through the event loop which is
> crucial for your GUI to appear responsive in other ways.

A question about CallAfter: As I understand, this function is intended
to be used from within threads, where it queues the operation to be
performed in the GUI queue.
But in this example there are no other threads except for the GUI
thread itself, from which CallAfter is called.
How does it work in this situation? Does it queue the opreation for
some idle time or does it perform it right away?
I thought that it probably performs it immediately in this case so it
is exactly like calling the operation directly.

And another question, if I may, I used to make tight loops in windows
API, planting inside them a command that processes messages from the
GUI queue and returns when no more messages exists. Something like
this:

loop {
  operations
  process_gui_messages
}

The loop ran quickly and the GUI remained responsive during the loop.
I did it on window API using a function I defined similar to this one:

void ProcessMessages()
{
  while (PeekMessage()) {
TranslateMessage(..);
DispatchMessage(..);
  }
}

This technique is not good for long loops, where the user may activate
other long GUI opreations during the tight loop and make a mess.
But it carries out the job well where during the time of the loop the
user may only access to certain features, such as pressing a button to
cancel the operation, operating the menu to exit the program, etc.
This scheme saves some state-machine code that is required when using
event-based programming.

Does wxPython have something like ProcessMessages?

Thanks
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread Carl Banks
On Mar 8, 12:35 pm, iu2  wrote:
> On Mar 8, 1:42 pm, Carl Banks  wrote:
>
>
>
> > On Mar 8, 1:52 am, iu2  wrote:
>
> > > On Mar 6, 6:52 pm, Mike Driscoll  wrote:
>
> > > > ...
> > > > Can you post a sample application so we can try to figure out what's
> > > > wrong? You might also cross-post this to thewxPythonmailing list.
> > > > They might know.
>
> > > > Mike- Hide quoted text -
>
> > > > - Show quoted text -
>
> > > Hi, thanks for your reply
>
> > > Here is a sample application:
>
> > > --
>
> > > import wx
> > > import time
>
> > > class My_frame(wx.Frame):
> > >     def __init__(self):
> > >         wx.Frame.__init__(self, None, -1, 'Moving panel')
> > >         self.surface = p = wx.Panel(self, size=(300, 130))
> > >         self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
> > >         self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
> > >         btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
> > >         self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)
>
> > >         self.Fit()
>
> > >     def move_panel(self, evt):
> > >         def gen():
> > >             for x in range(200):
> > >                 yield x
> > >             for x in range(200, 0, -1):
> > >                 yield x
> > >         for x in gen():
> > >             self.square.SetPosition((x, 30))
> > >             time.sleep(0.005)
>
> > >     def on_paint_square(self, evt):
> > >         square = evt.GetEventObject()
> > >         dc = wx.BufferedPaintDC(square)
> > >         dc.Pen = wx.Pen('blakc', 2)
> > >         dc.Brush = wx.Brush('light blue')
> > >         dc.DrawRectangle(0, 0, *square.GetSize())
>
> > > app = wx.PySimpleApp()
> > > My_frame().Show()
> > > app.MainLoop()
>
> > > --
>
> > > Press the button and the panel moves to the right and then back to the
> > > left.
> > > While PyScripter is running the panel moves at a certain speed. You
> > > can run the application from the Windows explorer with the same speed.
> > > You don't need to run it from PyScripter.
> > > When PyScripter is closed, the application runs much less quickly.
> > > I experienced this on two PC-s.
> > > Maybe this behavior is not even related towxPythonbut to the sleep
> > > command. I don't know...
>
> > It's not a good idea to call time.sleep inside a loop inside an event
> > handler, which is what you are doing here.
>
> > wx has a mechanism to call some sort of callback at timed intervals.
> > (I don't know what it is but I know it has one.)  Instead of animating
> > the box move inside the button callback, have it request that a
> > callback be called after x seconds pass, and draw a single frame
> > inside that callback.  Then invoke it again until you're done drawing.
>
> > Here's a rough idea of what that might look like:
>
> > class My_frame(wx.Frame):
>
> >     # ... among other things ...
>
> >     def move_panel(self,evt):
> >         self.square_pos = 0
> >         wx.set_timed_callback_of_some_sort(
> >             self.draw_frame,0.005)
>
> >     def draw_frame(self):
> >         self.square.SetPosition((self.square_pos, 30))
> >         self.square_pos += 1
> >         if self.square_pos < 200:
> >             wx.set_timed_callback_of_some_sort(
> >                self.draw_frame,0.005)
>
> > As for why it works fine in PyScripter but not when started from
> > Explorer, well, let's just say that when you abuse callbacks like you
> > did, you shouldn't expect reasonable behavior.
>
> > Carl Banks
>
> Hi,
>
> Here is the timer version. It works even more slowly, even with
> PyScripter active:
>
> --
> import wx
> import time
>
> class My_frame(wx.Frame):
>     def __init__(self):
>         wx.Frame.__init__(self, None, -1, 'Moving panel')
>         self.surface = p = wx.Panel(self, size=(300, 130))
>         self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
>         self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
>         btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
>         self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)
>
>         self.Fit()
>
>     def on_paint_square(self, evt):
>         square = evt.GetEventObject()
>         dc = wx.BufferedPaintDC(square)
>         dc.Pen = wx.Pen('blakc', 2)
>         dc.Brush = wx.Brush('light blue')
>         dc.DrawRectangle(0, 0, *square.GetSize())
>
>     def move_panel(self, evt):
>         def gen():
>             for x in range(200):
>                 yield x
>             for x in range(200, 0, -1):
>                 yield x
>         self.track = gen()
>         self.timer = wx.Timer(self)
>         self.Bind(wx.EVT_TIMER, self.on_timer_square, self.timer)
>         self.timer.Start(milliseconds=1)
>
>     def on_timer_square(self, evt):
>         try:
>             x = self.track.next()
>             self.square.SetPosition((x, 30))
>         e

Re: wxPython fast and slow

2009-03-08 Thread David Bolen
iu2  writes:

> Indeed, but I don't think the CallAfter is necessary. I could just as
> well remove the time.sleep in the original code. I could also make a
> tight loop to replace time.sleep
> for i in range(100): pass
> and tune it to fit the speed I need.

Except that CallAfter passed control back through the event loop which is
crucial for your GUI to appear responsive in other ways.

> I haven't mention this, but I actually want something to be the same
> speed on different PC-s. So a timer seems to fit in.

Then even a time.sleep() or plain loop isn't sufficient since each may
have additional latencies depending on load.  You will probably need
to query a system clock of some type to verify when your interval has
passed.

> I just can't make it work.
> Using wx.Timer is too slow.
> Using time.sleep is fast with PyScripter active, and slow when it is
> closed.

I have to admit to thinking that perhaps you're trying to operate too
quickly if you need better resolution than wx.Timer.  Most screen
operations don't have to appear that frequently to still appear
smooth, but that's your call.

Of course, even wx.Timer may be subject to other latencies if the
system or your application is busy with other events, so it depends
on how critical precise your timing needs to be.

You might also try an idle event, implementing your own timer (using
whatever call gives you the best resolution on your platform), and
just ignoring idle events that occur more frequently than the timing
you want.  Just remember to always request a new event.  You could do
the same thing with CallAfter as well, just reschedule a new one if
the current one is faster than your preferred interval.

-- David

--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread iu2
On Mar 9, 12:44 am, Scott David Daniels  wrote:
> iu2 wrote:
> > Here is the timer version. It works even more slowly, even with
> > PyScripter active: ...
>
> > I actually tried this one first. Due to the slow speed I changed to
> > looping inside the event.
> > I don't understand why it takes so long to move that square with
> > wx.Timer set to 1 ms interval. Perhaps its minimum interval is
> > actually 10 ms (as in Windows) so 100 steps really take 1 second.
> > But in that case, I really want to move the square in a tight loop
> > inside the wx.EVT_BUTTON event.
>
> > So allow me to rephrase my question:
> > Is there a way to move that square quickly and smoothly? Should 400
> > one-pixel moves should take so long on a 2.8 GHz core duo?
>
> > There is certainly something wrong in the code I wrote which I need
> > your help to figure out.
> > Can it be related to recurring paint events? If so how should I change
> > the code?
>
> > Thanks
>
> Here is a too-fast version you could fiddle around with:
>
> import wx
>
> class My_frame(wx.Frame):
>      def __init__(self):
>          wx.Frame.__init__(self, None, -1, 'Moving panel')
>          self.surface = p = wx.Panel(self, size=(300, 130))
>          self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
>          self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
>          btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
>          self.Bind(wx.EVT_BUTTON, self.startcalls, btn_move)
>          self.Fit()
>
>      def startcalls(self, evt=None):
>          def gen():
>              for x in range(200):
>                  yield x
>              for x in range(200, 0, -1):
>                  yield x
>          self.track = gen().next
>          wx.CallAfter(self.stepcall)
>
>      def stepcall(self, evt=None):
>          try:
>              x = self.track()
>          except StopIteration:
>              pass
>          else:
>              self.square.SetPosition((x, 30))
>              wx.CallAfter(self.stepcall)
>
>      def on_paint_square(self, evt):
>          square = evt.GetEventObject()
>          dc = wx.BufferedPaintDC(square)
>          dc.Pen = wx.Pen('black', 2)
>          dc.Brush = wx.Brush('light blue')
>          dc.DrawRectangle(0, 0, *square.GetSize())
>
> if __name__ == '__main__':
>      app = wx.PySimpleApp()
>      My_frame().Show()
>      app.MainLoop()

Indeed, but I don't think the CallAfter is necessary. I could just as
well remove the time.sleep in the original code. I could also make a
tight loop to replace time.sleep
for i in range(100): pass
and tune it to fit the speed I need.

I haven't mention this, but I actually want something to be the same
speed on different PC-s. So a timer seems to fit in.

I just can't make it work.
Using wx.Timer is too slow.
Using time.sleep is fast with PyScripter active, and slow when it is
closed.
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread Scott David Daniels

iu2 wrote:

Here is the timer version. It works even more slowly, even with
PyScripter active: ...

I actually tried this one first. Due to the slow speed I changed to
looping inside the event.
I don't understand why it takes so long to move that square with
wx.Timer set to 1 ms interval. Perhaps its minimum interval is
actually 10 ms (as in Windows) so 100 steps really take 1 second.
But in that case, I really want to move the square in a tight loop
inside the wx.EVT_BUTTON event.

So allow me to rephrase my question:
Is there a way to move that square quickly and smoothly? Should 400
one-pixel moves should take so long on a 2.8 GHz core duo?

There is certainly something wrong in the code I wrote which I need
your help to figure out.
Can it be related to recurring paint events? If so how should I change
the code?

Thanks


Here is a too-fast version you could fiddle around with:

import wx

class My_frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Moving panel')
self.surface = p = wx.Panel(self, size=(300, 130))
self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
self.square.Bind(wx.EVT_PAINT, self.on_paint_square)

btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
self.Bind(wx.EVT_BUTTON, self.startcalls, btn_move)
self.Fit()

def startcalls(self, evt=None):
def gen():
for x in range(200):
yield x
for x in range(200, 0, -1):
yield x
self.track = gen().next
wx.CallAfter(self.stepcall)

def stepcall(self, evt=None):
try:
x = self.track()
except StopIteration:
pass
else:
self.square.SetPosition((x, 30))
wx.CallAfter(self.stepcall)


def on_paint_square(self, evt):
square = evt.GetEventObject()
dc = wx.BufferedPaintDC(square)
dc.Pen = wx.Pen('black', 2)
dc.Brush = wx.Brush('light blue')
dc.DrawRectangle(0, 0, *square.GetSize())


if __name__ == '__main__':
app = wx.PySimpleApp()
My_frame().Show()
app.MainLoop()
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread iu2
On Mar 8, 1:42 pm, Carl Banks  wrote:
> On Mar 8, 1:52 am, iu2  wrote:
>
>
>
> > On Mar 6, 6:52 pm, Mike Driscoll  wrote:
>
> > > ...
> > > Can you post a sample application so we can try to figure out what's
> > > wrong? You might also cross-post this to thewxPythonmailing list.
> > > They might know.
>
> > > Mike- Hide quoted text -
>
> > > - Show quoted text -
>
> > Hi, thanks for your reply
>
> > Here is a sample application:
>
> > --
>
> > import wx
> > import time
>
> > class My_frame(wx.Frame):
> >     def __init__(self):
> >         wx.Frame.__init__(self, None, -1, 'Moving panel')
> >         self.surface = p = wx.Panel(self, size=(300, 130))
> >         self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
> >         self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
> >         btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
> >         self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)
>
> >         self.Fit()
>
> >     def move_panel(self, evt):
> >         def gen():
> >             for x in range(200):
> >                 yield x
> >             for x in range(200, 0, -1):
> >                 yield x
> >         for x in gen():
> >             self.square.SetPosition((x, 30))
> >             time.sleep(0.005)
>
> >     def on_paint_square(self, evt):
> >         square = evt.GetEventObject()
> >         dc = wx.BufferedPaintDC(square)
> >         dc.Pen = wx.Pen('blakc', 2)
> >         dc.Brush = wx.Brush('light blue')
> >         dc.DrawRectangle(0, 0, *square.GetSize())
>
> > app = wx.PySimpleApp()
> > My_frame().Show()
> > app.MainLoop()
>
> > --
>
> > Press the button and the panel moves to the right and then back to the
> > left.
> > While PyScripter is running the panel moves at a certain speed. You
> > can run the application from the Windows explorer with the same speed.
> > You don't need to run it from PyScripter.
> > When PyScripter is closed, the application runs much less quickly.
> > I experienced this on two PC-s.
> > Maybe this behavior is not even related towxPythonbut to the sleep
> > command. I don't know...
>
> It's not a good idea to call time.sleep inside a loop inside an event
> handler, which is what you are doing here.
>
> wx has a mechanism to call some sort of callback at timed intervals.
> (I don't know what it is but I know it has one.)  Instead of animating
> the box move inside the button callback, have it request that a
> callback be called after x seconds pass, and draw a single frame
> inside that callback.  Then invoke it again until you're done drawing.
>
> Here's a rough idea of what that might look like:
>
> class My_frame(wx.Frame):
>
>     # ... among other things ...
>
>     def move_panel(self,evt):
>         self.square_pos = 0
>         wx.set_timed_callback_of_some_sort(
>             self.draw_frame,0.005)
>
>     def draw_frame(self):
>         self.square.SetPosition((self.square_pos, 30))
>         self.square_pos += 1
>         if self.square_pos < 200:
>             wx.set_timed_callback_of_some_sort(
>                self.draw_frame,0.005)
>
> As for why it works fine in PyScripter but not when started from
> Explorer, well, let's just say that when you abuse callbacks like you
> did, you shouldn't expect reasonable behavior.
>
> Carl Banks

Hi,

Here is the timer version. It works even more slowly, even with
PyScripter active:

--
import wx
import time

class My_frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Moving panel')
self.surface = p = wx.Panel(self, size=(300, 130))
self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
self.square.Bind(wx.EVT_PAINT, self.on_paint_square)

btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)

self.Fit()

def on_paint_square(self, evt):
square = evt.GetEventObject()
dc = wx.BufferedPaintDC(square)
dc.Pen = wx.Pen('blakc', 2)
dc.Brush = wx.Brush('light blue')
dc.DrawRectangle(0, 0, *square.GetSize())

def move_panel(self, evt):
def gen():
for x in range(200):
yield x
for x in range(200, 0, -1):
yield x
self.track = gen()
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.on_timer_square, self.timer)
self.timer.Start(milliseconds=1)

def on_timer_square(self, evt):
try:
x = self.track.next()
self.square.SetPosition((x, 30))
except StopIteration:
self.timer.Stop()

app = wx.PySimpleApp()
My_frame().Show()
app.MainLoop()
-

I actually tried this one first. Due to the slow speed I changed to
looping inside the eve

Re: wxPython fast and slow

2009-03-08 Thread Mike Driscoll
On Mar 8, 3:52 am, iu2  wrote:
> On Mar 6, 6:52 pm, Mike Driscoll  wrote:
>
> > ...
> > Can you post a sample application so we can try to figure out what's
> > wrong? You might also cross-post this to thewxPythonmailing list.
> > They might know.
>
> > Mike- Hide quoted text -
>
> > - Show quoted text -
>
> Hi, thanks for your reply
>
> Here is a sample application:
>
> --
>
> import wx
> import time
>
> class My_frame(wx.Frame):
>     def __init__(self):
>         wx.Frame.__init__(self, None, -1, 'Moving panel')
>         self.surface = p = wx.Panel(self, size=(300, 130))
>         self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
>         self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
>         btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
>         self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)
>
>         self.Fit()
>
>     def move_panel(self, evt):
>         def gen():
>             for x in range(200):
>                 yield x
>             for x in range(200, 0, -1):
>                 yield x
>         for x in gen():
>             self.square.SetPosition((x, 30))
>             time.sleep(0.005)
>
>     def on_paint_square(self, evt):
>         square = evt.GetEventObject()
>         dc = wx.BufferedPaintDC(square)
>         dc.Pen = wx.Pen('blakc', 2)
>         dc.Brush = wx.Brush('light blue')
>         dc.DrawRectangle(0, 0, *square.GetSize())
>
> app = wx.PySimpleApp()
> My_frame().Show()
> app.MainLoop()
>
> --
>
> Press the button and the panel moves to the right and then back to the
> left.
> While PyScripter is running the panel moves at a certain speed. You
> can run the application from the Windows explorer with the same speed.
> You don't need to run it from PyScripter.
> When PyScripter is closed, the application runs much less quickly.
> I experienced this on two PC-s.
> Maybe this behavior is not even related to wxPython but to the sleep
> command. I don't know...
>
> Thanks
> iu2

You probably want to use wx.Timer rather than using time.sleep. You
could use wx.Sleep() too. I don't really understand why you're doing
what you're doing though. Did you re-post to the wxPython group?

Mike
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread John Posner

> def move_panel(self, evt):
> def gen():
> for x in range(200):
> yield x
> for x in range(200, 0, -1):
> yield x
> for x in gen():
> self.square.SetPosition((x, 30))
> time.sleep(0.005)
> 

I can't help with the performance problem, but you don't really need a 
generator for your x-values. This works:

def move_panel(self, evt):
for i in xrange(400):
x = 200-abs(i-200)
self.square.SetPosition((x, 30))
time.sleep(0.005)

The generator *does* make for clearer code, though!

-John

--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread Carl Banks
On Mar 8, 1:52 am, iu2  wrote:
> On Mar 6, 6:52 pm, Mike Driscoll  wrote:
>
> > ...
> > Can you post a sample application so we can try to figure out what's
> > wrong? You might also cross-post this to thewxPythonmailing list.
> > They might know.
>
> > Mike- Hide quoted text -
>
> > - Show quoted text -
>
> Hi, thanks for your reply
>
> Here is a sample application:
>
> --
>
> import wx
> import time
>
> class My_frame(wx.Frame):
>     def __init__(self):
>         wx.Frame.__init__(self, None, -1, 'Moving panel')
>         self.surface = p = wx.Panel(self, size=(300, 130))
>         self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
>         self.square.Bind(wx.EVT_PAINT, self.on_paint_square)
>
>         btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
>         self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)
>
>         self.Fit()
>
>     def move_panel(self, evt):
>         def gen():
>             for x in range(200):
>                 yield x
>             for x in range(200, 0, -1):
>                 yield x
>         for x in gen():
>             self.square.SetPosition((x, 30))
>             time.sleep(0.005)
>
>     def on_paint_square(self, evt):
>         square = evt.GetEventObject()
>         dc = wx.BufferedPaintDC(square)
>         dc.Pen = wx.Pen('blakc', 2)
>         dc.Brush = wx.Brush('light blue')
>         dc.DrawRectangle(0, 0, *square.GetSize())
>
> app = wx.PySimpleApp()
> My_frame().Show()
> app.MainLoop()
>
> --
>
> Press the button and the panel moves to the right and then back to the
> left.
> While PyScripter is running the panel moves at a certain speed. You
> can run the application from the Windows explorer with the same speed.
> You don't need to run it from PyScripter.
> When PyScripter is closed, the application runs much less quickly.
> I experienced this on two PC-s.
> Maybe this behavior is not even related to wxPython but to the sleep
> command. I don't know...

It's not a good idea to call time.sleep inside a loop inside an event
handler, which is what you are doing here.

wx has a mechanism to call some sort of callback at timed intervals.
(I don't know what it is but I know it has one.)  Instead of animating
the box move inside the button callback, have it request that a
callback be called after x seconds pass, and draw a single frame
inside that callback.  Then invoke it again until you're done drawing.

Here's a rough idea of what that might look like:



class My_frame(wx.Frame):

# ... among other things ...

def move_panel(self,evt):
self.square_pos = 0
wx.set_timed_callback_of_some_sort(
self.draw_frame,0.005)

def draw_frame(self):
self.square.SetPosition((self.square_pos, 30))
self.square_pos += 1
if self.square_pos < 200:
wx.set_timed_callback_of_some_sort(
   self.draw_frame,0.005)


As for why it works fine in PyScripter but not when started from
Explorer, well, let's just say that when you abuse callbacks like you
did, you shouldn't expect reasonable behavior.


Carl Banks
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-08 Thread iu2
On Mar 6, 6:52 pm, Mike Driscoll  wrote:
> ...

> Can you post a sample application so we can try to figure out what's
> wrong? You might also cross-post this to thewxPythonmailing list.
> They might know.
>
> Mike- Hide quoted text -
>
> - Show quoted text -

Hi, thanks for your reply

Here is a sample application:

--

import wx
import time

class My_frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Moving panel')
self.surface = p = wx.Panel(self, size=(300, 130))
self.square = wx.Panel(p, -1, size=(100, 100), pos=(0, 30))
self.square.Bind(wx.EVT_PAINT, self.on_paint_square)

btn_move = wx.Button(p, -1, 'Move panel', pos=(0, 0))
self.Bind(wx.EVT_BUTTON, self.move_panel, btn_move)

self.Fit()

def move_panel(self, evt):
def gen():
for x in range(200):
yield x
for x in range(200, 0, -1):
yield x
for x in gen():
self.square.SetPosition((x, 30))
time.sleep(0.005)


def on_paint_square(self, evt):
square = evt.GetEventObject()
dc = wx.BufferedPaintDC(square)
dc.Pen = wx.Pen('blakc', 2)
dc.Brush = wx.Brush('light blue')
dc.DrawRectangle(0, 0, *square.GetSize())

app = wx.PySimpleApp()
My_frame().Show()
app.MainLoop()

--

Press the button and the panel moves to the right and then back to the
left.
While PyScripter is running the panel moves at a certain speed. You
can run the application from the Windows explorer with the same speed.
You don't need to run it from PyScripter.
When PyScripter is closed, the application runs much less quickly.
I experienced this on two PC-s.
Maybe this behavior is not even related to wxPython but to the sleep
command. I don't know...

Thanks
iu2


--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-06 Thread Lie Ryan

iu2 wrote:


Do you have any idea of what is going wrong?



I think this might be related to the OS's process prioritization, 
focused Windows would get more priority than background window.

--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-06 Thread Mike Driscoll
On Mar 6, 8:41 am, iu2  wrote:
> Hi guys,
>
> Can you please help me with this:
> I wrote a little game in wxPython where I move small panels (showing
> bitmaps (100 x 100)) on the screen.
>
> This is similar to the code I wrote:
>
> for i in xrange(1, steps + 1):
>     my_panel.SetPosition(...)
>     time.sleep(0.1 / steps)
>
> I use PyScripter (Windows) for writing the application. While
> PyScripter is active, the panels move quickly. But when I exit
> PyScripter and execute the script from the explorer or the command
> line, the panels move very slowly.
>
> Do you have any idea of what is going wrong?
> Thank you very much
>
> iu2

Can you post a sample application so we can try to figure out what's
wrong? You might also cross-post this to the wxPython mailing list.
They might know.

Mike
--
http://mail.python.org/mailman/listinfo/python-list


Re: wxPython fast and slow

2009-03-06 Thread Almar Klein
That's weird. It might have to do with the main loop.
I am not familiar with pyscripter, but it might supply
a wx mainloop. However, if that is the case, I would
expect the app to run slower in pyscripter, not when
run without it...

So can you use wx interactively from pyscripter?
In other words, can you use the command line when
wx windows are active?

Cheers,
  Almar

2009/3/6 iu2 

> Hi guys,
>
> Can you please help me with this:
> I wrote a little game in wxPython where I move small panels (showing
> bitmaps (100 x 100)) on the screen.
>
> This is similar to the code I wrote:
>
> for i in xrange(1, steps + 1):
>my_panel.SetPosition(...)
>time.sleep(0.1 / steps)
>
> I use PyScripter (Windows) for writing the application. While
> PyScripter is active, the panels move quickly. But when I exit
> PyScripter and execute the script from the explorer or the command
> line, the panels move very slowly.
>
> Do you have any idea of what is going wrong?
> Thank you very much
>
> iu2
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
http://mail.python.org/mailman/listinfo/python-list


wxPython fast and slow

2009-03-06 Thread iu2
Hi guys,

Can you please help me with this:
I wrote a little game in wxPython where I move small panels (showing
bitmaps (100 x 100)) on the screen.

This is similar to the code I wrote:

for i in xrange(1, steps + 1):
my_panel.SetPosition(...)
time.sleep(0.1 / steps)

I use PyScripter (Windows) for writing the application. While
PyScripter is active, the panels move quickly. But when I exit
PyScripter and execute the script from the explorer or the command
line, the panels move very slowly.

Do you have any idea of what is going wrong?
Thank you very much

iu2

--
http://mail.python.org/mailman/listinfo/python-list