Drawing in "Slow motion". 
Author Message
 Drawing in "Slow motion".

Hello.

I have written a small script concerned with some drawing into a Canvas
widget
(The actual drawing procedure is triggered by an event bound to a
Button).

My problem is that I would like the program to draw one line at a time;
then
pause, then draw the next line... and so on.

I have tried to insert pauses by calling time.seep,
however, the drawing operations are realized only
when the drawing procedure ends and program control is resumed by

root.mainloop()

Any suggestions?

Thanx in advance

- hans kristian -



Sat, 31 Jul 2004 22:27:03 GMT  
 Drawing in "Slow motion".
Hi Hans,

Quote:

> I have written a small script concerned with some drawing into a Canvas
> widget
> (The actual drawing procedure is triggered by an event bound to a
> Button).

> My problem is that I would like the program to draw one line at a time;
> then
> pause, then draw the next line... and so on.

> I have tried to insert pauses by calling time.seep,
> however, the drawing operations are realized only
> when the drawing procedure ends and program control is resumed by

> root.mainloop()

Two solutions come to my mind:
- keep your time.sleep calls, but call the update_idletasks method on the
canvas after each sleep. The call should redraw the screen.
- a bit trickier: use the delayed callback facility in Tk via the "after"
method to draw while your application is running. This is a bit more
complicated and you would certainly have to rewrite your code differently.
But it's the only way to have a "reacting" application while the drawing
takes place (i.e. user is able to click on buttons, call menus, etc...).
Here is a simple example, just drawing random lines:

--------------------------------------------
import random
from Tkinter import *

w, h = 500, 500
x, y = random.randrange(w), random.randrange(h)

root = Tk()
cnv = Canvas(root, width=w, height=h)
cnv.pack(side=TOP)
Button(root, text='Enough', command=root.quit).pack(side=TOP)

def f(*whatever):
  global x, y
  oldx, oldy = x, y
  x, y = random.randrange(w), random.randrange(h)
  cnv.create_line(oldx, oldy, x, y)
  root.after(500, f)

root.after(500, f)
root.mainloop()
--------------------------------------------

HTH
 - eric -



Sat, 31 Jul 2004 23:55:41 GMT  
 Drawing in "Slow motion".

Quote:

> Hi Hans,

> Two solutions come to my mind:
> - keep your time.sleep calls, but call the update_idletasks method on the
> canvas after each sleep. The call should redraw the screen.
> - a bit trickier: use the delayed callback facility in Tk via the "after"
> method to draw while your application is running. This is a bit more
> complicated and you would certainly have to rewrite your code differently.
> But it's the only way to have a "reacting" application while the drawing
> takes place (i.e. user is able to click on buttons, call menus, etc...).
> Here is a simple example, just drawing random lines:

Thanx a lot; these solutions were very helpful.

Quote:

> HTH
>  - eric -

- hans kristian -


Sat, 31 Jul 2004 23:04:40 GMT  
 Drawing in "Slow motion".

Quote:

> - keep your time.sleep calls, but call the update_idletasks method on the
> canvas after each sleep. The call should redraw the screen.
> - a bit trickier: use the delayed callback facility in Tk via the "after"
> method to draw while your application is running. This is a bit more
> complicated and you would certainly have to rewrite your code differently.

if you're using 2.2, you can replace the call to time.sleep() with a
yield, and add a small wrapper like the "func" function below:

from __future__ import generators

import random
from Tkinter import *

w, h = 500, 500

root = Tk()
cnv = Canvas(root, width=w, height=h)
cnv.pack(side=TOP)
Button(root, text='Enough', command=root.quit).pack(side=TOP)

def draw():
    x, y = random.randrange(w), random.randrange(h)
    while 1:
        oldx, oldy = x, y
        x, y = random.randrange(w), random.randrange(h)
        cnv.create_line(oldx, oldy, x, y)
        yield 500 # sleep

def func(iter):
    root.after(iter.next(), func, iter)

func(draw()) # get things going

mainloop()

</F>

<!-- (the eff-bot guide to) the python standard library:
http://www.pythonware.com/people/fredrik/librarybook.htm
-->



Sat, 31 Jul 2004 23:42:15 GMT  
 Drawing in "Slow motion".

Quote:


> > ...(The actual drawing procedure is triggered by an event bound to a
> > Button).
> > My problem is that I would like the program to draw one line at a time;
> > then pause, then draw the next line... and so on....
> Two solutions come to my mind:
> - keep your time.sleep calls, but call the update_idletasks method on the
> canvas after each sleep. The call should redraw the screen.
> - a bit trickier: use the delayed callback facility in Tk via the "after"
> method to draw while your application is running...

Here is a solution that requires less "program inversion" on your
actual drawing.  The "yield" of the drawing generator is used to do
the inversion.  Obviously, 2.2 is required.  Code shamelessly stolen
from Eric Brunel's fine example.

from __future__ import generators
import random
from Tkinter import *

w, h = 500, 500
root = Tk()
cnv = Canvas(root, width=w, height=h)
cnv.pack(side=TOP)

def draw(count):
    """A generator that draws with a 'yield' at each time point."""
    x, y = random.randrange(w), random.randrange(h)
    for i in range(count):
        oldx, oldy = x, y
        x, y = random.randrange(w), random.randrange(h)
        cnv.create_line(oldx, oldy, x, y)
        yield None

# Put in a button to walk through the drawing
Button(root, text='Click', command=draws(10).next).pack(side=TOP)

# Put in a button to do a "timed" walk through the drawing

def per_tick():
    """This gets executed once per 'tick' to do the drawing"""
    try:
        draw_step()
        root.after(500, per_tick)
    except StopIteration:
        pass

def timed():
    "Once per button push: set up the generator for per_tick, and start it."""
    global draw_step
    draw_step = draw(17).next
    root.after(500, per_tick)

Button(root, text='Timed', command=timed).pack(side=TOP)




Sun, 01 Aug 2004 04:21:52 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. string.join(["Tk 4.2p2", "Python 1.4", "Win32", "free"], "for")

2. Simple Drawing Program to capture "doodling"

3. MSWL and "draw window"

4. "use" slow on remote computer -- Win95

5. Slow "recording" on winXP Command

6. "Slow surfing enters a new dimension"?

7. "wm deiconify" is sometimes really slow

8. SUMMARY: writing "not slow" smalltalk (long)

9. BEGIN{want[]={"s1o", "s2o", "s2q", "s3q"}

10. Parsing ""D""?

11. "Fifth", "Forth", zai nar?

12. Ruby "finalize", "__del__"

 

 
Powered by phpBB® Forum Software