Version 19 of Tcl::Tk

Updated 2008-10-07 14:45:13 by Xyem

Tcl::Tk is an alternative binding to Tcl/Tk from Perl (as opposed to Perl/Tk). It uses Tcl in the bridge (which Perl/Tk does not). These are the Tcl [L1 ] and Tcl::Tk [L2 ] modules for Perl. Make sure you get the latest.

Mailing lists:

wiki:

Tcl::Tk has advantages over the traditional Perl/Tk in using less memory and being faster, as well as being more portable and flexible (for example, for use on Windows/CE). It gains this by linking directly against Tcl using a bridge that has deep understanding of Tcl_Objs and PerlSVs. It has a slightly varied interface, but there is a rough Perl/Tk compatability layer (about 80% compatability). It would be nice to see another module layered on top that provides near 100% Perl/Tk compability while maintaining the efficient lower layer that ties tightly to Tcl.

VK: Other advantages of Tcl, Tcl::Tk perl modules over Perl/Tk are briefly listed at perl's discussion site [L3 ]:

  • Perl<->Tcl/Tk bridge is lightweight, any misbehaviour is hidden is 70Kb of pure-perl Tcl::Tk code and 30Kb of Tcl bridge code; perlTk is huge and really hard to maintain. It took really many efforts to switch to Unicode between versions Tk800.024 <->Tk804.027
  • Most up-to-date Tcl/Tk could easily be used. Tcl-8.5 is really soon to come, and I already tried it from Perl.
  • You can use Unicode GUI in Perl version 5.6.x, and perlTk lacks support for Unicode for 5.6.x.
  • You have a much richier set of widgets, plus pure-Tcl widgets, and the many widget extensions developed for Tcl/Tk.
  • It is the only way to have Perl+Tk GUI on WinCE devices. PerlTk is harder to port to another platform, and perlTk Unicode version is not ported to WinCE (only elder one).
  • True native OS X (Aqua) Tk is usable.
  • As a general rule, it is easier to maintain structured things. That said, Perl does its own evolving, and Tcl/Tk does its own. Contrary, perlTk contains "Tk" and "Tix" mixed in it, and you do not know how old they are, plus some pure-Perl widgets that do not have Tcl/Tk counterpart, and perlTk documentation contains a lot of documentation rudiments that fixed in Tcl/Tk
  • Perl motto "TIMTOWTDI" is wider: you can do
 $interpreter->Eval('pure-tcl-code-to-create-and-manipulate-widgets');

or use perlTk syntax

 my $btn=$frame->Button(-text=>'Ok',-command=>sub{print 'ok'})->pack;

Disadvantage and major compat issue over Perl/Tk is lack of documented way for creating of pure-perl widgets. This is currently work in progress. It is all technically possible, just needs to be done. Since Tcl::Tk is open to the world of Tcl/Tk widget sets (BLT, BWidget, Tix, tile, iwidgets, vu, Tktable, ...), developers of new (from scratch) apps may find it easier to use these, but compat for older apps should remain a consideration.

Following example shows how Perl program can use Tcl::Tk to access Tcl/Tk. It creates and then uses pure-perl widget LabEntry2 based on mkWidgets package:

 use Tcl::Tk;

 my $int = new Tcl::Tk;
 my $mw = $int->mainwindow;

 #
 # make pure-perl widget
 #
 # 1. bring mkWidgets package, it provides megawidgets (among others are snit, Tix, BWidget, IWidgets)
 $int->pkg_require('mkWidgets');
 # 2. create metawidget
 # our megawidget will have two labels and two edit boxes, aligned, with
 # a 'frustrate' button that swaps two Entry subwidgets
 # 2.1 metawidget itself
 $int->metawidgetCreate('LabEntry2', sub {
         #print STDERR "init proc: instantiation of a metawidget; create internal widgets\n";
         my $this = $int->widget($int->GetVar('this'));
         my $lab1 = $this->Label->grid(-column=>0,-row=>0,-sticky=>'e');
         my $ed1 = $this->Entry->grid(-column=>1,-row=>0,-sticky=>'w');
         my $lab2 = $this->Label->grid(-column=>0,-row=>1,-sticky=>'e');
         my $ed2 = $this->Entry->grid(-column=>1,-row=>1,-sticky=>'w');
         my $btn = $this->Button(-text=>'frustrate',-command=>sub{$this->frustrate})
             ->grid(-column=>0,-row=>2,-sticky=>'we',-columnspan=>2);
         $int->my('lab1',$lab1->path);
         $int->my('ed1',$ed1->path);
         $int->my('lab2',$lab2->path);
         $int->my('ed2',$ed2->path);
     }, sub {
         print STDERR "exit proc: destruction of a metawidget; delete internal widgets\n";
         my $this = $int->widget($int->GetVar('this'));
         # do I need deleting child widgets? those are deleted automatically
         for ($this->children) {
             print STDERR "\@\@";
             $_->destroy;
         }
     });
 # 2.2 some of its methods/options
 $int->metawidgetCommand('LabEntry2', frustrate=> sub {
         my $this = $int->widget($int->GetVar('this'));
         # frustrate method of our megawidget swaps two entry subwidgets, so user will be frustrated
         $int->_gridForget($int->my('ed1'),$int->my('ed2'));
         $int->_grid($int->my('ed1'),qw/-column 1 -row 1 -sticky w/);
         $int->_grid($int->my('ed2'),qw/-column 1 -row 0 -sticky w/);
     });
 # ... options
 $int->metawidgetOption('LabEntry2', '-lab1', sub {
         my (undef,$int,undef,$aa) = @_;
         $int->my('-lab1',$aa);
         $int->widget($int->my('lab1'))->configure(-text=>$aa);
     });
 $int->metawidgetOption('LabEntry2', '-lab2', sub {
         my (undef,$int,undef,$aa) = @_;
         $int->my('-lab2',$aa);
         $int->widget($int->my('lab2'))->configure(-text=>$aa);
     });
 $int->metawidgetOption('LabEntry2', '-textvariable1', sub {
         my (undef,$int,undef,$aa) = @_;
         $int->widget($int->my('ed1'))->configure(-textvariable=>$aa);
     });
 $int->metawidgetOption('LabEntry2', '-textvariable2', sub {
         my (undef,$int,undef,$aa) = @_;
         $int->widget($int->my('ed2'))->configure(-textvariable=>$aa);
     });

 # 3. now Tcl/Tk has our megawidget; bring it to Perl
 $mw->Declare('LabEntry2','labentry2');

 # megawidget creation completed. now use it
 my ($v1,$v2,$v3) = qw(one two three);
 my $mywid = $mw->LabEntry2(-lab1=>'l1',-lab2=>'l2',-textvariable1=>\$v1,-textvariable2=>\$v2)->pack;
 my $mywid1 = $mw->LabEntry2(-lab1=>'XXX',-lab2=>'O',-textvariable1=>\$v1,-textvariable2=>\$v3)->pack;

 # I wonder what is 2nd label of 2nd widget?
 print STDERR "2nd label of 2nd widget is ",$mywid1->cget('-lab2'),"\n";

 $mw->Scrolled('Text')->pack(-fill=>'both',-expand=>1)->_insertEnd("".$int->_infoBody('tclPkgUnknown'));
 $int->MainLoop;

Pure-perl widgets based on other Tcl approaches will be also added.


RLH - Since both are PM modules can I just drop them in my lib path (on Windows XP) and be off and running?

VK - Tcl::Tk is pure perl, but Tcl module is not (has XS). Perl module with a name Tcl is trivial to compile. Look /ask for/... in Tcl::Tk wiki for binaries.


Examples

by Xyem

Building Tcl for Tcl 8.5:

The Tcl module ( 0.97 ) tries to use stubs for Tcl 8.4 which results in a segmentation error when the Tcl module is used in Perl, despite passing all tests. To create the Makefile for building it for Tcl 8.5 on my Ubuntu ( 8.04 ) machine I used:

  perl Makefile.PL --nousestubs --library=-ltcl8.5  --include=-I/usr/include/tcl8.5/