technoleap84
technoleap84

Reputation: 228

Perl Tk: Canvas dynamic updating

I'm trying to animate the results of a mathematical process in a 2D canvas with Tk. I've decided to do it with Tk and not SDL because right now i'm working with both Linux and Windows machines and Strawberry Perl doesn't compile proberly in windows, whil Tk is up on both pcs.

What i would like to do with Tk is that:

1)Popping up the canvas while my program is working out the coordinates of the points i would like to draw.

2)Drawing them instantly into the canvas without waiting for the process to reach the end

It's actually a simple animation, where a bunch of points moves around the Canvas while my script updates their coordinates.

Here you have a code snippet i've been writing so far for a single point:

use Tk;

#calcuate the coordinate of a single point
$x=10;
$y=10;
$top = MainWindow->new();

# create a canvas widget
$canvas = $top->Canvas(width => 600, height => 400) -> pack();

# For example, let's create 1 point inside the canvas
$canvas->create ('oval', $x, $y, $x+3, $y+3, -fill=>"black");  # fill color of object

MainLoop;

The problem with the above code is that i would like to add my 'math' script inside it in order to update the $x and $y coordinates above (with some sort of for/while cycle) without shutting down the original canvas, by obtaining a single point moving all around it (atually there are more points i'm supposed to display but that's a minor detail). FYI, using a simple for cycle embedding the ''Mainloop'' directive doesn't fix the problem.

Thanks in advance guys

Upvotes: 2

Views: 557

Answers (2)

technoleap84
technoleap84

Reputation: 228

SOLUTION:

As per Stefan Becker suggested option nr.2, here is what has finally fixed the problem:

use Tk:

$top = MainWindow->new();

# create a canvas widget
$canvas = $top->Canvas(width => 600, 
                        height => 400,
                        background => 'black') -> pack();

$x=300; 
$y=200; 

my $update = sub {
    $canvas->delete('all'); #unquote this line if you don't want the original point positions to be drawn in the canvas. Viceversa
    $x=$x+(-5+rand(10)); #white noise
    $y=$y-(-5+rand(10)); #white noise
    $canvas->create ('oval', $x , $y , $x+5, $y+5, -fill=>"red"); 
    };  

    $top->repeat(50, $update); 

MainLoop;

I've just added the statement $canvas->delete('all') at the beginning of the updating loop in order to draw just actual points and not the history.

Upvotes: 1

Stefan Becker
Stefan Becker

Reputation: 5962

Quoting from Mastering Perl/Tk, chapter 15 "Anatomy of the MainLoop":

Option 1: use your own MainLoop implementation

use Tk qw(:eventtypes);

while (Tk::MainWindow->Count) {
    # process events - but don't block waiting for them
    DoOneEvent(ALL_EVENTS | DONT_WAIT);

    # your update implementation goes here
}

Option 2: use a repeat timer event

Later in the chapter it is stated that DoOneEvent() isn't really necessary for most stuff. You could use timer events instead, e.g.

my $update = sub {
    # your update implementation goes here
};

# run update every 50ms
$top->repeat(50, $update);

MainLoop;

Upvotes: 2

Related Questions