6

在 1980 年代的 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 了吗?

如果您想知道我的意思是什么,没有事件循环图形库,请参阅这个链接的论文,不幸的是它是针对 C 的。这样的东西对于科学知识非常有用,除了介绍性编程课程之外。

4

4 回答 4

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;
于 2012-10-01T02:29:11.340 回答
1

我推荐使用 Perl 模块Inline::C。该模块使您可以轻松地将 C 库公开给您的 Perl 应用程序。对于某些 C 库,“AUTOWRAP”选项使其变得非常简单。但即使您必须自己编写一些包装器,Inline::C 也确实减轻了 XS 的负担。

于 2012-10-01T05:00:09.100 回答
0

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

于 2012-09-30T13:11:09.267 回答
0

我认为您在这种情况下有点错过了GLib/之类的情节。无需分叉GTK即可处理;GTK事实上,如果你做 fork 之类的事情,你很可能在那里做错了。您所描述的内容应该很容易使用GTK.

于 2012-09-30T17:03:43.727 回答