The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Tcl::Tk - Extension module for Perl giving access to Tk via the Tcl extension

SYNOPSIS

    use Tcl::Tk qw(:widgets);
    $interp = new Tcl::Tk;
    label(".l", -text => "Hello world");
    $interp->pack(".l");
    MainLoop;

Or

    use Tcl::Tk;
    $interp = new Tcl::Tk;
    $interp->label(".l", -text => "Hello world")->pack;
    $btn = $interp->button(".btn", -text => "test", -command => sub {
      $btn->configure(-text=>"[". $btn->cget('-text')."]");
    })->pack;
    $interp->MainLoop;

Or even perl/Tk compatible way:

    use Tcl::Tk qw(:perlTk);
    $mw = MainWindow->new;
    $mw->Label(-text => "Hello world")->pack;
    $btn = $mw->Button(-text => "test", -command => sub {
      $btn->configure(-text=>"[". $btn->cget('-text')."]");
    })->pack;
    MainLoop;

DESCRIPTION

The Tcl::Tk submodule of the Tcl module gives access to the Tk library. It does this by creating a Tcl interpreter object (using the Tcl extension) and binding in all of Tk into the interpreter (in the same way that wish or other Tcl/Tk applications do).

Unlike perlTk extension (available on CPAN), where Tk+Tix are embedded into extension, this module connects to existing TCL installation. Such approach allows to work with most up-to-date TCL, and this automatically gives Unicode and pure TCL widgets available to application along with any widgets existing in TCL installation. As an example, Windows user have possibility to use ActiveX widgets provided by Tcl extension named "OpTcl", so to provide native Windows widgets.

Please see and try to run demo scripts 'demo.pl', 'demo-w-tix.pl' and 'widgets.pl' in 'demo' directory of source tarball.

Access to the Tcl and Tcl::Tk extensions

To get access to the Tcl and Tcl::Tk extensions, put the commands near the top of your program.

    use Tcl;
    use Tcl::Tk;

Another (and better) way is to use perlTk compatibility mode by writing:

    use Tcl::Tk qw(:perlTk);

Creating a Tcl interpreter for Tk

To create a Tcl interpreter initialised for Tk, use

    $i = new Tcl::Tk (DISPLAY, NAME, SYNC);

All arguments are optional. This creates a Tcl interpreter object $i, and creates a main toplevel window. The window is created on display DISPLAY (defaulting to the display named in the DISPLAY environment variable) with name NAME (defaulting to the name of the Perl program, i.e. the contents of Perl variable $0). If the SYNC argument is present and true then an XSynchronize() call is done ensuring that X events are processed synchronously (and thus slowly). This is there for completeness and is only very occasionally useful for debugging errant X clients (usually at a much lower level than Tk users will want).

Entering the main event loop

The Perl method call

    $i->MainLoop;

on the Tcl::Tk interpreter object enters the Tk event loop. You can instead do Tcl::Tk::MainLoop or Tcl::Tk->MainLoop if you prefer. You can even do simply MainLoop if you import it from Tcl::Tk in the use statement. Note that commands in the Tcl and Tcl::Tk extensions closely follow the C interface names with leading Tcl_ or Tk_ removed.

Creating widgets

As a general rule, you need to consult TCL man pages to realize how to use a widget, and after that invoke perl command that creates it properly.

If desired, widgets can be created and handled entirely by Tcl/Tk code evaluated in the Tcl interpreter object $i (created above). However, there is an additional way of creating widgets in the interpreter directly from Perl. The names of the widgets (frame, toplevel, label etc.) can be imported as direct commands from the Tcl::Tk extension. For example, if you have imported the label command then

    $l = label(".l", -text => "Hello world");

executes the command

    $i->call("label", ".l", "-text", "Hello world");

and hence gets Tcl to create a new label widget .l in your Tcl/Tk interpreter. You can either import such commands one by one with, for example,

    use Tcl::Tk qw(label canvas MainLoop winfo);

or you can use the pre-defined Exporter tags :widgets and :misc. The :widgets tag imports all the widget commands and the :misc tag imports all non-widget commands (see the next section).

When creating a widget, you must specify its path as first argument. Widget path is a string starting with a dot and consisting of several names separated by dots. These names are widget names that comprise widget's hierarchy. As an example, if there exists a frame with a path ".fram" and you want to create a button on it and name it "butt" then you should specify name ".fram.butt". Widget paths are refered in miscellaneous widget operations, and geometry management is one of them. Once again, see Tcl/Tk documentation to get details.

Widget creation command returns a Perl object that could be used further for operations with widget. Perl method calls on the object are translated into commands for the Tcl/Tk interpreter in a very simplistic fashion. For example, the Perl command

    $l->configure(-background => "green");

is translated into the command

    $i->call("$l", "configure", "-background", "green");

for execution in your Tcl/Tk interpreter. Notice that it simply stringifies the object to find the widget name. There is no automagic conversion that happens: if you use a Tcl command which wants a widget pathname and you only have an object returned by label() (or button() or entry() or whatever) then you must stringify it yourself.

When widgets are created they are stored internally and could be retreived by widget() command:

    widget(".fram.butt")->configure(-text=>"new text");
   

Please note that this method will return to you a widget object even if it was not created within this module, and check will not be performed whether a widget with given path exists, despite of fact that checking for existence of a widget is an easy task (invoking $interp->Eval("info commands $path") will do this). Instead, you will receive perl object that will try to operate with widget that has given path even if such path do not exists.

This approach allows to transparently access widgets created somewhere inside Tcl/Tk processing. So variable $btn in following code will behave exactly as if it was created with "button" method:

    $interp->Eval(<<'EOS');
    frame .f
    button .f.b
    pack .f
    pack .f.b
    EOS
    my $btn = widget(".f.b");

Note, that widget() method does not checks whether required widget actually exists in Tk. It just will return an object of type Tcl::Tk::Widget and any method of this widget will just ask underlying Tcl/Tk GUI system to do some action with a widget with a given path. In case it do not actually exist you will receive an error from Tcl/Tk.

To check if a widget with a given path exists use Tcl::Tk::Exists($widget) subroutine. It queries Tcl/Tk for existance of said widget.

awidget method

If you know there exists a method that creates widget in Tcl/Tk but it is not implemented as a part of this module, use awidget method (mnemonic - "a widget" or "any widget"). awidget, as method of interpreter object, creates a subroutine inside Tcl::Tk package and this subroutine could be invoked as a method for creating desired widget. After such call any interpreter can create required widget.

If there are more than one arguments provided to awidget method, then newly created method will be invoked with remaining arguments:

  $interp->awidget('tixTList');
  $interp->tixTList('.f.tlist');

does same thing as

  $interp->awidget('tixTList', '.f.tlist');

awidgets method

awidgets method takes a list consisting of widget names and calls awidget method for each of them.

Widget creation commands are methods of Tcl::Tk interpreter object. But if you want to omit interpreter for brevity, then you could do it, and in this case will be used interpreter that was created first. Following examples demonstrate this:

    use Tcl::Tk qw(:widgets);
    $interp = new Tcl::Tk;

    # at next line interpreter object omited, but $interp is implicitly used
    label ".l", -text => "Hello world"; 
    
    widget(".l")->pack; # $interp will be called to pack ".l"
    
    # OO way, we explicitly use methods of $interp to create button
    $btn = $interp->button(".btn", -text => "test", -command => sub {
      $btn->configure(-text=>"[". $btn->cget('-text')."]");
    });
    $btn->pack; # another way to pack a widget

    $interp->MainLoop;

Button, Frame, Text, Canvas and similar methods

If you do not feel like to invent a widget path name when creating new widget, Tcl::Tk can automatically generate them for you. Each widget has methods to create another widgets.

Suppose you have 'frame' in variable $f with a widget path '.f'. Then $btn=$f->Button(-command => sub{\&useful}); will create a button with a path like '.f.b02' and will assign this button into $btn.

This syntax is very similar to syntax for perlTk. Some perlTk program even will run unmodified with use of Tcl::Tk module.

widget_data method

If you need to associate any data with particular widget, you can do this with widget_data method of either interpreter or widget object itself. This method returns same anonymous hash and it should be used to hold any keys/values pairs.

Examples:

  $interp->widget_data('.fram1.label2')->{var} = 'value';
  $label->widget_data()->{var} = 'value';

Non-widget Tk commands

For convenience, the non-widget Tk commands (such as destroy, focus, wm, winfo and so on) are also available for export as Perl commands and translate into into their Tcl equivalents for execution in your Tk/Tcl interpreter. The names of the Perl commands are the same as their Tcl equivalents.

BUGS

Currently work is in progress, and some features could change in future versions.

AUTHORS

Malcolm Beattie, mbeattie@sable.ox.ac.uk Vadim Konovalov, vkonovalov@peterstar.ru, 19 May 2003. Jeff Hobbs, jeffh _a_ activestate com, February 2004. Gisle Aas, gisle _a_ activestate . com, 14 Apr 2004.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html