Question

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.

Was it helpful?

Solution

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;

OTHER TIPS

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.

I'm not exactly sure what your end goal is, and this may not help, but perhaps you want to look at David Merten's App::Prima::REPL. David has been building a plotting library for Perl/PDL built on the Prima graphical toolkit. To take it to its logical extreme, he built a REPL around it, making a GUI REPL with plotting built-in. As you say, Prima relies on an event-loop to function, however, because you are inside a REPL you still can direct the REPL to plot new data. His goal is scientific use too!

I think you somewhat missed the plot of things like GLib/GTK in that case. It's very-much possible to handle GTK without forking; in fact if you do things like fork you are likely doing it wrong there. What you describe should be easily possible using GTK.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top