Perl Tk:画布动态更新

时间:2019-02-07 18:37:01

标签: perl canvas tk

我正在尝试使用Tk在2D画布中对数学过程的结果进行动画处理。我决定使用Tk而不是SDL进行操作,因为现在我同时在Linux和Windows机器上工作,Strawberry Perl不会在Windows中进行详细的编译,而Tk在两台电脑上都有效。

我想用Tk做的是:

1)在我的程序正在计算要绘制的点的坐标时弹出画布。

2)将它们立即绘制到画布中,而无需等待过程结束

这实际上是一个简单的动画,当我的脚本更新其坐标时,一堆点围绕“画布”移动。

这里有一个我到目前为止一直在写的代码段:

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;

上面的代码的问题是我想在其中添加我的'math'脚本,以更新上面的$ x和$ y坐标(使用某种for / while循环)而无需关闭原始脚本通过获得一个在画布上移动的单个点(通常我应该显示更多点,但这只是次要的细节)。 仅供参考,使用简单的循环嵌入“ Mainloop”指令无法解决问题。

预先感谢

2 个答案:

答案 0 :(得分:2)

引自Mastering Perl/Tk,第15章“ MainLoop的剖析”:

选项1:使用自己的MainLoop实现

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
}

选项2:使用重复计时器事件

在本章后半部分中指出,DoOneEvent()对于大多数内容并不是必需的。您可以改用计时器事件,例如

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

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

MainLoop;

答案 1 :(得分:1)

解决方案:

根据Stefan Becker建议的选项nr.2,这终于解决了问题:

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;

我刚刚在更新循环的开头添加了语句$ canvas-> delete('all'),以便仅绘制实际点而不是历史。