Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No event loop graphics in Perl plus X Window?

On the Apple II BASIC in the 1980s, you would use "HGR", to get to a screen, "HCOLOR" would set a color, and "HPLOT" would plot points. You could also manipulate the screen byte data, and you wouldn't have to hand off program control to any event handler. This ridiculously rudimentary functionality seems to be missing today from every language and every library.

So I wrote a small library to do this in C using the X Window API: HGR(x,y) puts up an XWindow, HCOLOR(i) sets the color, and HPLOT(i,j) plots a point, plus you extract the window's bitmap and can modify it and display the modified thing. This was not straightforward, and I don't want to go through it again.

I am using Perl for some things now, and I need such a tool for Perl, something where you can call a subroutine that preferably returns without spawning a new thread, having output a window, where you can add graphical stuff to the window, and query the events when your program feels like it. This is the functionality of 1980s BASIC, so it shouldn't be hard. But the tools I saw didn't do it:

  • GD: As far as I could see, this makes graphics files, not graphics windows. It seems you need to pipe it to another program.
  • Gtk2: I have to fork out a separate thread to catch the events, otherwise it won't display the window. I don't want to fork anything, and I mostly don't care about any events, not unless I specifically ask to see the stuff piled up in the queue later.
  • Qt: Here you are also expected to hand off control to the event handler, no handing off, no display. In the C++ version, I could get Qt to display and draw without a handoff.
  • PerlTk: Again with the stupid handoff.
  • OpenGL: Here, I don't know how to catch X Window events, like a keypress, when I feel like looking at what happened.

Does anyone know how to put up an XWindow from a running application, without forking out a GUI application process, where you can draw primitive things in the window like points and lines, and where you can query your windows' events on your own schedule? I briefly looked at the X Window API for Perl, it's as horrendous as C, and interfacing the C code with Perl is also horrendous. If necessary, I'll do it. But maybe not. Is there an HGR for Perl already?

If you are wondering what I mean, no event loop graphical library, see this linked paper, which unfortunately is for C. Such a thing is extremely useful for scientific stuff, outside of introductory programming classes.

like image 685
Ron Maimon Avatar asked Sep 30 '12 02:09

Ron Maimon


2 Answers

Pretty much every GUI toolkit supports building windows without entering the event loop. Here is tk example

#!/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__

Both Gtk2 and Wx support the same thing, its either update/show/display ... and the windows get drawn, and when you want user interaction, you call MainLoop or run the app or handle it yourself, its just a while loop dispatching pending events

wxTheApp->Dispatch       while wxTheApp->Pending;
Gtk2->main_iteration     while Gtk2->events_pending;
like image 197
so not liopa Avatar answered Oct 28 '22 10:10

so not liopa


I recommend using the Perl module Inline::C. That module makes it easy to expose a C library to your Perl application. With some C libraries the 'AUTOWRAP' option makes it completely trivial. But even if you have to write some wrappers yourself, Inline::C really eases the XS burden.

like image 39
DavidO Avatar answered Oct 28 '22 09:10

DavidO