views:

627

answers:

4

I have several simple Perl programs writing to the standard output, but this has some problems :

  • some of my users are scared by a console
  • my users works on Windows, so my program output is displayed on a cmd console, so I cannot control the way it is displayed (colors and terminal size), and worse, the console is not resizeable (at least in width)

To solve these problems, I would like to be able to display the output in a simple GUI interface as an option. The GUI should be responsive until the program finishes (it should be possible to scroll or resize the window while it's running).

What the simple toolkit and widget I can use to do this? (I develop on Windows with ActivePerl).

+4  A: 

From a quick search you do have a few options:

  1. Perl with NCurses (its a GUI, but it keeps it in the console)
  2. Perl with wxWindows wxPerl
  3. PerlTK
  4. GTK with Perl (see the wikibooks reference)

Also, there is a wikibooks reference for this.

monksy
Perl with NCurses does not solve my problem, and with wxPerl, PerlTK or GTK, how do I redirect my console output?
Jazz
You would have to create a standardized way of communicating with a GUI app which runs the console app and sends in input. Or you could rewrite the application.
monksy
I hoped something already existed that solved this problem...
Jazz
There isn't a shared standard for outputing to the console, so there is no magic process in automatically converting a console app to a GUI based app.
monksy
+1  A: 

wxWidgets using Wx CPAN module is popular in Perl world right now (see Padre)

However I'm not sure this comes with ActivePerl which I believe may come with Tk instead.

/I3az/

draegtun
How does it solve my console output problem?
Jazz
As of 5.10 ActivePerl comes with Tkx instead of Tk, although Tk is still available via PPM. (Tkx is an alternative set of bindings to Tcl/Tk.)
Michael Carman
@Jazz - Instead of playing around with STDOUT you could consider a message/logging queue option? For eg. something like Message::Stack (http://search.cpan.org/dist/Message-Stack/).
draegtun
I could use Tie::STDOUT or Message::Stack, it is not really a problem. My remaining problem is how I can have a responsive GUI displaying the output while the program runs.
Jazz
+9  A: 

You can use any GUI option you like, and then you could use Tie::STDOUT to redefine the behavior of print and printf to the STDOUT filehandle to instead dump output into the widget of your choice. The only thing is that getting it to talk to your widgets across packages cleanly using the anonymous sub might be messy. Here's a short, crude example using Win32::GUI:

use Win32::GUI();
use Tie::STDOUT 
    print => sub {
     $main::textfield->Append(@_);
    };

my $main = Win32::GUI::Window->new(
        -name => 'Main',
        -text => 'Perl',
        -width => 220,
        -height => 230,
    );
our $textfield = $main->AddTextfield(
        -name   => "Output",
        -left   => 8,
        -top    => 8,
        -width  => 180,
        -height => 180,
        -readonly => 1,
        -multiline => 1,
        -vscroll => 1,
    );
$main->Show();
sub Main_Terminate {
        -1;
}


if(!fork()) {
    print "Hello.\n";
    for (1..20) {
      sleep 1;
      printf "More output %d\n", $_;
    }
} else {
    Win32::GUI::Dialog();
}

Note the call to Win32::GUI::Dialog() at the end is present to keep the window from closing as soon as the script is finished.

Adam Bellaire
It's a good start. One problem remains: the GUI is unresponsive until the program reaches Win32::GUI::Dialog. Maybe I should try using 2 threads?
Jazz
@Jazz: Yeah, actually you can use `fork()`, the windows fork emulation will handle it for you. I've edited my answer to show the change.
Adam Bellaire
+3  A: 

If you have Firefox installed on the machines, I've been working on the module XUL::Gui which lets you display your Perl gui using Firefox's rendering engine. Building on Adam's answer:

use XUL::Gui;
use Tie::STDOUT 
    print => sub {$ID{text}->value .= join '' => @_};

display Window title=>'Perl', minwidth=>640, minheight=>480,
    TextBox( FILL SCROLL id=>'text', multiline=>'true' ),
    delay {
        print "hello world\n";  # Output goes to the window.
        for (1..5) {
            printf "More output %d\n", $_;
        }
    };

Edit: fixed a bug with multi-line return values from the gui, example above is nicer now. works with XUL::Gui 0.35+

Eric Strom
Just looking at the code, I'd expect `.= join($,, @_) . $\\`, but I haven't actually played with it to see.
ephemient
@ephemient => thanks, updated
Eric Strom