Perl和X Window中没有事件循环图形?

时间:2012-09-30 02:13:25

标签: perl graphics event-loop

在20世纪80年代的Apple II BASIC上,您将使用“HGR”进入屏幕,“HCOLOR”将设置颜色,“HPLOT”将绘制点。您还可以操作屏幕字节数据,而不必将程序控制交给任何事件处理程序。今天,每种语言和每个图书馆似乎都缺少这种荒谬的基本功能。

所以我使用X Window API在C中编写了一个小型库:HGR(x,y)表示XWindow,HCOLOR(i)设置颜色,HPLOT(i,j)图一个点,再加上你提取窗口的位图,可以修改它并显示修改过的东西。这不是直截了当的,我不想再经历它了。

我现在正在使用Perl,我需要Perl这样的工具,你可以调用一个子程序,最好在没有产生新线程的情况下返回,输出一个窗口,你可以在其中添加图形内容。窗口,并在程序感觉到时查询事件。这是1980年代BASIC的功能,所以它应该不难。但我看到的工具没有这样做:

  • GD:据我所知,这会产生图形文件,而不是图形窗口。看来你需要将它传递给另一个程序。
  • Gtk2:我必须派出一个单独的线程来捕获事件,否则它将不会显示窗口。我不想分叉任何东西,我大多不关心任何事件,除非我特意要求稍后看到堆积在队列中的东西。
  • Qt:在这里,您还需要将控制权移交给事件处理程序,不要切换,不显示。在C ++版本中,我可以在没有切换的情况下显示和绘制Qt。
  • PerlTk:再次与愚蠢的交接。
  • OpenGL:在这里,当我想看看发生的事情时,我不知道如何捕捉X Window事件,比如按键。

有没有人知道如何从正在运行的应用程序中放置一个XWindow,而不需要执行GUI应用程序进程,您可以在窗口中绘制原始内容,如点和线,以及在哪里可以查询窗口中的事件自己的日程?我简要地看了一下Perl的X Window API,它和C一样可怕,并且将C代码与Perl连接起来也是可怕的。如有必要,我会这样做。但也许不是。 Perl有没有HGR?

如果您想知道我的意思,没有事件循环图形库,请参阅this linked paper,遗憾的是C语言。这对于科学的东西非常有用,除了介绍性编程类之外。

4 个答案:

答案 0 :(得分:4)

几乎每个GUI工具包都支持构建窗口而无需进入事件循环。这是tk示例

#!/usr/bin/perl --
use strict;
use warnings;
use Tk;
my $mw = tkinit();
my $ca = $mw->Canvas(
    background => 'white'
)->pack(qw/-expand 1 -fill both /);
$mw->geometry( '500x600+10+10' );
for my $cc (
    { red   => \&red, green => \&der, blue => \&erd },
    { green => \&red, red   => \&der, blue => \&erd },
    { green => \&red, blue  => \&der, red  => \&erd },
  )
{
    $ca->delete('all');
    my %color = %$cc;

    for my $fill ( keys %color ) {
        my $red = $color{$fill};
        for my $t ( 10 .. 220 ) {
            my $d = 0.1;
            my ( $x, $y ) = $red->( $t, 0.1 );
            $_ += 250 for $x, $y;
            $ca->createOval(
                $x, $y,
                ( $t * 2 * $d ) + $x,
                ( $t * 2 * $d ) + $y,
                -fill => $fill,
            );
            $mw->update;
            select undef, undef, undef, 0.001;
        }
        $mw->update;
    }
}

Tk::DoOneEvent(0) while Tk::MainWindow->Count; ## MainLoop;
exit 0;

sub red {
    my ( $t, $d ) = @_;
    my $x = $t * sin( $t * $d );
    my $y = $t * cos( $t * $d );
    $x, $y;
}

sub der {
    my ( $t, $d ) = @_;
    my $x = $t * sin( $t * $d );
    my $y = $t * cos( $t * 2 * $d );
    $x, $y;
}

sub erd {
    my ( $t, $d ) = @_;
    my $x = $t * sin( $t * 2 * $d );
    my $y = $t * cos( $t * $d );
    $x, $y;
}

__END__

Gtk2和Wx都支持同样的事情,它更新/显示/显示......并且窗口被绘制,当你想要用户交互时,你可以调用MainLoop或运行应用程序或自己处理它,它只是一个while循环调度待处理事件

wxTheApp->Dispatch       while wxTheApp->Pending;
Gtk2->main_iteration     while Gtk2->events_pending;

答案 1 :(得分:1)

我建议使用Perl模块Inline::C。该模块可以轻松地将C库公开给Perl应用程序。对于一些C库,'AUTOWRAP'选项使其完全无关紧要。但即使您必须自己编写一些包装器,Inline :: C也可以减轻XS负担。

答案 2 :(得分:0)

我不确定你的最终目标是什么,这可能无济于事,但也许你想看看David Merten的App::Prima::REPL。 David一直在为plotting library图形工具包构建的Perl / PDL构建Prima。为了使其达到逻辑极限,他围绕它构建了一个REPL,使用内置的绘图制作GUI REPL。如你所说,Prima依赖于一个事件循环来运行,但是,因为你在REPL中,你仍然可以指示REPL绘制新数据。他的目标也是科学用途!

答案 3 :(得分:0)

在这种情况下,我认为你有点错过GLib / GTK之类的情节。在没有分叉的情况下处理GTK非常有可能;事实上,如果你做像fork这样的事情,你很可能在那里做错了。您可以使用GTK轻松实现所描述的内容。