mascip has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,
I have read that Wx is faster than Tk, which makes me want to use it.
I will also need to use AnyEvent in order to do asynchronous HTTP requests and IO file operations. The solution thus seems to be Wx + AnyEvent.
But i have a dilema because of what AnyEvent's documentation says :

There is no direct support for WxWidgets (Wx).

WxWidgets has no support for watching file handles. However, you can use WxWidgets through the POE adaptor, as POE has a Wx backend that simply polls 20 times per second, which was considered to be too horrible to even consider for AnyEvent.

AnyEvent knows about Wx, however, and will try to load POE when detecting it, in the hope that POE will pick it up, in which case everything will be automatic.

Thus, i am considering using Tk or Gtk2/3 instead.

Could someone with some experience in the matter give me their opinion ?

I wouldn't like to start a project with a GUI Toolkit, and realize when the project gets bigger, that the GUI is too slow so i have to restart it from scratch.


PS : I didn't mention Tkx, as it is not mentioned in AnyEvent's documentation. Gtk3 is not mentioned either but i guess it will work, as it relies on Glib which works with AnyEvent.

Replies are listed 'Best First'.
Re: AnyEvent + Wx, Gtk2/3 or Tk ?
by zentara (Cardinal) on Dec 10, 2012 at 10:57 UTC
    I have read that Wx is faster than Tk

    I'm not sure where you heard that, or what sort of application they were talking about.

    If you want a filehandle watcher in Gtk2, you can do that, Gtk2 is pretty good in my book, although I never had trouble with Tk's speed, unless the number of widgets were very large.

    You can run mixed event loops by making one loop a master, and the other a slave. The slave loop gets pumped every so many milliseconds by a timer in the master loop. See Wx with Tk and here below is a Gtk2-Tk hybrid script. It may be useful.

    #!/usr/bin/perl -w use strict; use Gtk2; use Tk; #setup Tk loop my $mw = MainWindow->new(-title=>'Tk Window'); my $count_tk = 0; my $labtk = $mw->Label(-textvariable =>\$count_tk)->pack; #setup Gtk2 loop Gtk2->init; my $count_gtk = 0; my $window = Gtk2::Window->new('toplevel'); $window->set_title('Gtk2 Window'); my $glabel = Gtk2::Label->new("This is a Gtk2 Label $count_gtk"); $window->add($glabel); $window->show_all; # make Tk loop the master, but you could make Gtk2 master if desired # the lower the repeat rate, i.e. 1 ms, # will give more cpu time to the gtk2 loop # this is sometimes called manually pumping the event loop my $tktimer = $mw->repeat(10, sub{ $count_gtk++; $glabel->set_text("This is a Gtk2 Label $count_gtk"); Gtk2->main_iteration while Gtk2->events_pending; $count_tk++; }); $mw->Button(-text=>' Tk control Quit ', -command => sub{exit} )->pack(); MainLoop; ########################################

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      Hi zentara,

      Some time ago (about a year), I tried running your demonstration with background workers. Then forgotten about it until recently and thought lost. Notice the 1 ms repeat interval for no other reason than to see Gtk, Tk, and STDOUT go :) Well, am no longer worried about losing these two demonstrations for running background workers with Gtk2 and Tk.

      Gtk2 + Tk + MCE::Hobo + MCE::Shared

      #!/usr/bin/perl # Re: AnyEvent + Wx, Gtk2/3 or Tk ? # https://www.perlmonks.org/?node_id=1008085 use strict; use warnings; use Gtk2; use Tk; use MCE::Hobo; use MCE::Shared; use Time::HiRes 'time'; $| = 1; my $que = MCE::Shared->queue( fast => 1 ); my $count = MCE::Shared->scalar( 0 ); my $count_tk = 0; MCE::Hobo->create( sub { while (defined (my $c = $que->dequeue)) { print "$c\n"; } }) for (1..3); my $start = time; # setup Tk loop my $mw = MainWindow->new(-title=>'Tk Window'); my $labtk = $mw->Label(-textvariable => \$count_tk)->pack; # setup Gtk2 loop Gtk2->init; my $window = Gtk2::Window->new('toplevel'); $window->set_title('Gtk2 Window'); my $glabel = Gtk2::Label->new("This is a Gtk2 Label 0"); $window->add($glabel); $window->show_all; # make Tk loop the master, but you could make Gtk2 master if desired # the lower the repeat rate, i.e. 1 ms, # will give more cpu time to the gtk2 loop # this is sometimes called manually pumping the event loop my $tktimer = $mw->repeat( 1, sub { my $c = $count->incr; $count_tk = $c; $glabel->set_text("This is a Gtk2 Label $c"); Gtk2->main_iteration while Gtk2->events_pending; quit() if ($c >= 2000); $que->enqueue(($c) x 3); }); $mw->Button( -text => ' Tk control Quit ', -command => \&quit )->pack; $mw->protocol( WM_DELETE_WINDOW => \&quit ); MainLoop; sub quit { $tktimer->cancel(), $que->clear(), $que->end(); $_->kill('QUIT') for MCE::Hobo->list(); kill('TERM', -$$); exit; } END { printf "duration: %0.03f seconds\n", time - $start; }

      Regards, Mario

        The same demo using threads, again at the 1 ms repeat interval. Thread::Queue lacks the clear method and likely not necessary. Thought to clear the memory before the main process exits mainly to minimize any possibility for threads seg-faulting. Not yet sure if this is helpful. Was trying things at the time.

        Gtk2 + Tk + threads + Thread::Queue

        #!/usr/bin/perl # Re: AnyEvent + Wx, Gtk2/3 or Tk ? # https://www.perlmonks.org/?node_id=1008085 use strict; use warnings; use threads; use threads::shared; use Thread::Queue; use Gtk2; use Tk; use Time::HiRes 'time'; $| = 1; my $que = Thread::Queue->new(); my $count : shared = 0; my $count_tk = 0; sub Thread::Queue::clear { my ( $self ) = @_; lock $self; @{ $_[0]->{queue} } = (); return; } threads->create( sub { $SIG{QUIT} = sub { threads->exit(0) }; while (defined (my $c = $que->dequeue)) { print "$c\n"; } })->detach() for (1..3); my $start = time; # setup Tk loop my $mw = MainWindow->new(-title=>'Tk Window'); my $labtk = $mw->Label(-textvariable => \$count_tk)->pack; # setup Gtk2 loop Gtk2->init; my $window = Gtk2::Window->new('toplevel'); $window->set_title('Gtk2 Window'); my $glabel = Gtk2::Label->new("This is a Gtk2 Label 0"); $window->add($glabel); $window->show_all; # make Tk loop the master, but you could make Gtk2 master if desired # the lower the repeat rate, i.e. 1 ms, # will give more cpu time to the gtk2 loop # this is sometimes called manually pumping the event loop my $tktimer = $mw->repeat( 1, sub { my $c = ++$count; $count_tk = $c; $glabel->set_text("This is a Gtk2 Label $c"); Gtk2->main_iteration while Gtk2->events_pending; quit() if ($c >= 2000); $que->enqueue(($c) x 3); }); $mw->Button( -text => ' Tk control Quit ', -command => \&quit )->pack; $mw->protocol( WM_DELETE_WINDOW => \&quit ); MainLoop; sub quit { $tktimer->cancel(), $que->clear(), $que->end(); $_->kill('QUIT') for threads->list(); printf "duration: %0.03f seconds\n", time - $start; kill('TERM', -$$); exit; }

        Regards, Mario

      If i understood well, AnyEvent is made so that one doesn't need to "plug" loops together manually, like you just showed me how to do (thank you!).
      I think i'll go for an EV loop, with Gtk2 embedded (or Gtk3 if it works).

      My question was very naive : it's the first time in years that i implement a GUI, and the first time that i use events too.
      Thank you for reassuring me that Tk and Gtk2 are not slow. I don't remember where i read that Wx was faster, but these words can make newbies like me imagine that not-Wx is bound to be slow.

Re: AnyEvent + Wx, Gtk2/3 or Tk ?
by Anonymous Monk on Dec 10, 2012 at 03:55 UTC

    I will also need to use AnyEvent in order to do asynchronous HTTP requests and IO file operations. The solution thus seems to be Wx + AnyEvent.

    What is that?

    Yeah, the "watching filehandles" thing is undated -- the 2.9 branch has added some support, though a lot of that depends on the OS -- you can always use Glib with wxWidgets :) Hey, even perl doesn't support it :)

    I wouldn't like to start a project with a GUI Toolkit, and realize when the project gets bigger, that the GUI is too slow so i have to restart it from scratch.

    Prototype -- simulate the type of performance you're expecting, its trivial (say, creating 10,000 buttons and 200-100-line-text-widgets)

    But "HTTP requests and IO file operations" sounds wonderfully vague -- I don't think it'll matter what you choose

      Prototyping, very good idea, thank you! :-)