wxPython fast and slow
iu2
israelu at elbit.co.il
Sun Mar 8 15:35:20 EDT 2009
On Mar 8, 1:42 pm, Carl Banks <pavlovevide... at gmail.com> wrote:
> On Mar 8, 1:52 am, iu2 <isra... at elbit.co.il> wrote:
>
>
>
> > On Mar 6, 6:52 pm, Mike Driscoll <kyoso... at gmail.com> 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 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
More information about the Python-list
mailing list