NAME
Tcl::pTk - Interface to Tcl/Tk with Perl/Tk compatible syntax
SYNOPSIS
Perl/Tk Compatible Syntax:
use Tcl::pTk;
my $mw = MainWindow->new();
my $lab = $mw->Label(-text => "Hello world")->pack;
my $btn = $mw->Button(-text => "test", -command => sub {
$lab->configure(-text=>"[". $lab->cget('-text')."]");
})->pack;
MainLoop;
Or Tcl::pTk Synax with direct access to Tcl:
use Tcl::pTk;
my $int = new Tcl::pTk;
$int->Eval(<<'EOS');
# pure-tcl code to create widgets (e.g. generated by some GUI builder)
entry .e
button .inc -text {increment by Perl}
pack .e .inc
EOS
my $btn = $int->widget('.inc'); # get .inc button into play
my $e = $int->widget('.e'); # get .e entry into play
$e->configure(-textvariable=>\(my $var='aaa'));
$btn->configure(-command=>sub{$var++});
$int->MainLoop;
DESCRIPTION
Tcl::pTk
interfaces perl to an existing Tcl/Tk installation on your computer. It has fully perl/tk (See Tk) compatible syntax for running existing perl/tk scripts, as well as direct-tcl syntax for using any other Tcl/Tk features.
Using this module an interpreter object is created, which then provides access to all the installed Tcl libraries (Tk, Tix, BWidgets, BLT, etc) and existing features (for example native-looking widgets using the Tile
package).
Features
Perl/Tk compatible syntax.
Pure perl megawidgets work just like in perl/tk. See the test case t/slideMegaWidget.t in the source distribution for a simple example.
All the perl/tk widget demos work with minimal changes. Typically the only changes needed are just changing the
use Tk;
touse Tcl::pTk;
at the top of the file. See the widgetTclpTk demo script included in the source distribution to run the demos.Built-in local drag-drop support, compatible with perl/tk drag-drop coding syntax.
Tcl::pTk::TkHijack package supplied which enables Tcl::pTk to be used with existing Tk Scripts.
Similar interface approach to Tcl/Tk that other dynamic languages use (e.g. ruby, python). Because of this approach, upgrades to Tcl/Tk shouldn't require much coding changes (if any) in Tcl::pTk.
Tcl::pTk::Facelift package supplied, which provides a quick way of using the new better-looking Tile/ttk widgets in existing code.
TableMatrix (spreadsheet/grid Tktable widget, built to emulate the perl/tk Tk::TableMatrix interface ) built into the package (as long as you have the Tktable Tcl/Tk extension installed).
Extensive test suite.
Compatible with Tcl/Tk 8.4+
Examples
There are many examples in the widgetTclpTk script (This is very simlar to the widget demo installed with perl/tk). After installing the Tcl::pTk package, type widgetTclpTk on the command line to run.
The test cases in the t directory of the source distribution also is a good source of code examples.
Relation to the Tcl::Tk Package
This package (Tcl::pTk) is similar (and much of the code is derived from) the Tcl::Tk package, maintained by Vadim Konovalov. However it differs from the Tcl::Tk package in some important ways:
-
Emphasis is on 100% compatibility with existing perl/tk syntax.
For developers with a perl/Tk background and an existing perl/Tk codebase to support. For perl/Tk developers looking to take advantage of the look/feel updates in Tcl/Tk 8.5 and above.
-
Emphasis is on a lightweight interface to Tcl/Tk with syntax similar to (but not exactly like) perl/tk.
For developers with some perl/Tk background, writing new code, but no existing perl/Tk codebase to support.
Basic Usage/Operation
Creating a Tcl interpreter for Tk
Before you start using widgets, an interpreter (at least one) should be created, which will manage all things in Tcl. Creating an interpreter is created automatically by the call to the MainWindow
(or tkinit
) methods, but can also be created explicitly.
Example showing perl/Tk compatible syntax: For perl/tk syntax, the interpreter is created for you when you create the mainwindow.
use Tcl::pTk;
my $mw = MainWindow->new(); # Create Tcl::pTk interpreter and returns mainwindow widget
my $int = $mw->interp; # Get the intepreter that was created in the MainWindow call
Example showing explicit creation of an interpreter using Tcl::pTk:
use Tcl::pTk;
my $int = new Tcl::pTk;
Optionally a DISPLAY argument can be specified: my $int = new Tcl::pTk(":5");
. This creates a Tcl interpreter object $int, and creates a main toplevel window. The window is created on display DISPLAY (defaulting to the display named in the DISPLAY environment variable)
Entering the main event loop
Perl/Tk compatible syntax:
MainLoop; # Exact same syntax used as perl/Tk
Tcl::pTk Syntax:
$int->MainLoop;
Creating and using widgets
Two different approaches are used to manipulate widgets (or to manipulate any Tcl objects that act similarly to widgets).
Perl/Tk compatible-syntax approach. i.e.
$widget->method
syntax.Direct access using Eval-ed Tcl code. (e.g. using the
Eval
Tcl::pTk method)
The first way to manipulate widgets is identical to the perl/Tk calling conventions, the second one uses Tcl syntax. Both ways are interchangeable in that a widget created with one way can be used the another way. This interchangability enables use of Tcl-code created elsewhere (e.g. by some WYSIWYG IDE).
Usually Perl programs operate with Tcl::pTk via perl/Tk syntax, so users have no need to deal with the Tcl language directly. Only some basic understanding of Tcl/Tk widgets is needed.
Tcl/Tk syntax
In order to get better understanding on usage of Tcl/Tk widgets from within Perl, a bit of Tcl/Tk knowledge is needed, so we'll start from 2nd approach, with Tcl's Eval ($int->Eval('...')
) and then smoothly move to first approach with perl/Tk syntax.
The Tcl Interpreter
The Tcl interpreter is used to process Tcl/Tk widgets; within
Tcl::pTk
you create it withnew
, and given any widget object, you can retrieve it by the$widget->interp
method. ( Within pure Tcl/Tk the interpreter already exists, you don't need to create it explicitly. )The Widget Path
The Widget path is a string starting with a dot and consisting of several names separated by dots. These names are individual widget-names that comprise a 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 itbutt
, then you should specify name.fram.butt
. Widget paths are also referred in other miscellaneous widget operations, like geometry management.At any time a widget's path can be retrieved with
$widget->path;
withinTcl::pTk
.The Widget Path as a Tcl/Tk command
When a widget is created in Tcl/Tk, a special command is created that is the name of the widget's path. For example, a button created in a frame has a path and command-name
.fr.b
. This command also has subcommands which manipulate the widget. That is why$int->Eval('.fr.b configure -text {new text}');
makes sense. Note that using perl/tk syntax$button->configure(-text=>'new text');
does exactly the same thing, if$button
corresponds to.fr.b
widget.
The use Tcl::pTk;
statement not only creates the Tcl::pTk
package, but also creates the Tcl::pTk::Widget
package, which is responsible for widgets. Each widget ( an object blessed to Tcl::pTk::Widget
, or any of its subclasses ) behaves in such a way that its method will result in calling its path on the interpreter.
Perl/Tk syntax
Tcl::pTk
fully supports perl/Tk widget syntax of the Tk package, which has been used for many years. This means that any Tcl::pTk
widget has a number of methods like Button
, Frame
, Text
, Canvas
and so on, and invoking those methods will create an appropriate child widget. Tcl::pTk
will generate an unique path-name for a newly created widget.
To demonstrate this concept, the perl/Tk syntax:
my $label = $frame->Label(-text => "Hello world");
executes the command
$int->call("label", ".l", "-text", "Hello world");
and this command similar to
$int->Eval("label .l -text {Hello world}");
This way Tcl::pTk widget commands are translated to Tcl syntax and directed to the Tcl interpreter. This translation that occurs from perl/Tk syntax to Tcl calls is why the two approaches for dealing with widgets are interchangeable.
The newly created widget $label
will be blessed to package Tcl::pTk::Label
which is isa-Tcl::pTk::Widget
(i.e. Tcl::pTk::Label
is a subclass of Tcl::pTk::Widget
).
Categories of Tcl::pTk Widgets
Tcl::pTk
Widgets fall into the following basic categories, based on how they are implemented in the Tcl::pTk
package.
- Direct auto-wrapped widgets
-
These types of widgets (for example the Entry, Button, Scrollbar, and Label widgets) have no special code written for them in
Tcl::pTk
. Their creation and method calls (e.g.$button->configure(-text => 'ButtonText')
) are handled by the wrapping code in the base Tcl::pTk::Widget package. - Auto-wrapped widgets, with compatibility code
-
These types of widgets are similar to the Direct auto-wraped widgets, but have additional code written to be completely compatibile with the perl/Tk syntax. Examples of this type of widget are the Text, Frame, Menu, and Menubutton widgets.
- Megawidgets
-
These are widgets that are composed of one-or-more other base widget types. Pure-perl megawidgets are supported in Tcl::pTk, just like they are in perl/Tk. Examples of these types of widgets are ProgressBar, LabEntry, BrowseEntry, and SlideSwitch (one of the test cases in the source distribution).
- Derived Widgets
-
Derived widgets are sub-classes of existing widgets that provide some additional functions. Derived widgets are created in Tcl::pTk using very similar syntax to perl/Tk (i.e. using the Tcl::pTk::Derived package, similar to the Tk::Derived package). Examples of these types of widgets are Tree, TextEdit, TextUndo, ROText, and DirTree.
A behind-the-scenes look at auto-wrapped widgets
All widgets in Tcl::pTk
are objects, and have an inheritance hierarchy that derives from the Tcl::pTk::Widget
parent class. Megawidgets and derived widgets are handled very similar (if not exactly) the same as in perl/tk.
Auto-wrapped widgets (like the Entry, Button, Scrollbar, etc.) are handled differently. The object system for these types of widgets is dynamic. Classes and/or methods are created when they are first used or needed.
The following describes how methods are called for the two different categories of auto-wrapped widgets
- Direct auto-wrapped widget example
-
Here is an example of a Entry widget, a direct auto-wrapped widget:
my $entry = $mw->Entry->pack; # Create an entry widget and pack it $entry->insert('end', -text=>'text'); # Insert some text into the Entry my $entryText = $entry->get(); # Get the entry's text
Internally, the following mechanics come into play: The Entry method creates an Entry widget (known as
entry
in the Tcl/Tk environment). When this creation method is invoked the first time, a packageTcl::pTk::Entry
is created, which sets up the class hierarchy for any further Entry widgets. The newly-createdTcl::pTk::Entry
class is be a direct subclass ofTcl::pTk::Widget
.The second code line above calls the
insert
method of the$entry
object. When invoked first time, a method (i.e. subref)insert
is created in packageTcl::pTk::Entry
, which will end-up calling calling theinvoke
method on the Tcl/Tk interpreter (i.e.$entry->interp()->invoke($entry, 'insert', -text, 'text')
).The first time
insert
is called, theinsert
method does not exist, so AUTOLOAD comes into play and creates the method. The second timeinsert
is called, the already-created method is called directly (i.e. not created again), thus saving execution time. - Auto-wrapped widgets, with compatibility code
-
Here is an example of a Text widget, which is an auto-wrapped widget with extra code added for compatibility with the perl/tk Text widget.
my $text = $mw->Text->pack; # Create an text widget and pack it $text->insert('end', -text=>'text'); # Insert some text into the Text @names = $text->markNames; # Get a list of the marks set in the # Text widget
Internally, following mechanics come into play: The Text method creates an Text widget (known as
text
in Tcl/Tk environment). Because aTcl::pTk::Text
package already exists, a new package is not created at runtime like the case above.The second code line above calls the
insert
of the$text
object of typeTcl::pTk::Text
. Thisinsert
method is already defined in theTcl::pTk::Text
package, so it is called directly.The third code line above calls the
markNames
method on the$text
object. This method is not defined in theTcl::pTk::Text
package, so the first time whenmarkNames
is called, AUTOLOAD in the Tcl::pTk package comes into play and creates the method. The second timemarkNames
is called, the already-created method is called directly (i.e. not created again), thus saving execution time.
Description of an auto-wrapped method call
Suppose $widget
isa Tcl::pTk::Widget
, its path is .path
, and method method
invoked on it with a list of parameters, @parameters
:
$widget->method(@parameters);
In this case all @parameters
will be preprocessed by performing the following actions:
For each variable reference, a Tcl variable will be created and tied to it, so changes in the perl variable will be reflected in the Tcl variable, and changes in the Tcl variable will show up in the perl variable.
For each perl code-reference, a Tcl command will be created that calls this perl code-ref.
Each array reference will considered a callback, and proper actions will be taken.
After processing of @parameters
, the Tcl/Tk interpreter will be requested to perform following operation:
- if
$method
is all lowercase (e.g.insert
),m/^[a-z]$/
-
.path method parameter1 parameter2
.... - if
$method
contains exactly one capital letter inside the method name (e.g.tagNames
),m/^[a-z]+[A-Z][a-z]+$/
-
.path method submethod parameter1 parameter2
.... - if
$method
contains several capital letter inside the method name,methodSubmethSubsubmeth
-
.path method submeth subsubmeth parameter1 parameter2
....
Fast method invocation for auto-wrapped widgets
If you are sure that preprocessing of @parameters
in a method call aren't required (i.e. no parameters are Perl references to scalars, subroutines or arrays), then the preprocessing step described above can be skipped by calling the method with an underscore _
prepended to the name. (e.g call $text->_markNames()
, instead of $text->markNames()
). Calling the method this way means you are using an internal method that executes faster, but normally you should use a "public" (i.e. non-underscore) method, which includes all preprocessing.
Example:
# Can't use the faster method-call here, because \$var must be
# preprocessed for Tcl/Tk:
$button->configure(-textvariable=>\$var);
# Faster version of insert method for the "Text" widget
$text->_insert('end','text to insert','tag');
# This line does exactly same thing as previous line:
$text->_insertEnd('text to insert','tag');
When doing many inserts to a text widget, the faster version can help speed things up.
Using any Tcl/Tk feature from Tcl::pTk
In addition to the standard widgets (e.g. Entry, Button, Menu, etc), the Tcl::pTk
module lets you use any other widget from the Tcl/Tk widget library. This can be done with either Tcl syntax (via the Eval
method), or with regular perl/tk syntax.
To interface to a new Tcl/Tk widget using perl/tk syntax, a Declare
method call is made on an already-created widget, or on the Tcl::pTk
interpreter object itself.
Syntax is
# Calling Declare on a widget object:
$widget->Declare('perlTk_widget_method_name','tcl/tk-widget_method_name',
@options);
or, exactly the same,
# Calling Declare on a the Tcl::pTk Interpreter object:
$interp->Declare('perlTk_widget_method_name','tcl/tk-widget_method_name',
@options);
Options are:
-require => 'tcl-package-name'
-prefix => 'some-prefix'
The -require option specifies the new Tcl/Tk widget requires a Tcl package to be loaded with a name of 'tcl-package-name';
The -prefix option used to specify the prefix of the autogenerated widget path-name. This option is normally used when the Tcl/Tk widget name contains non-alphabetic characters (e.g. ':'). If not specified, the prefix will be generated from the package-name.
A typical example of using the Declare
method:
$mw->Declare('BLTNoteBook','blt::tabnotebook',-require=>'BLT',-prefix=>'bltnbook');
After this call, Tcl::pTk
will create a widget creation method for this new package to make it an auto-wrapped widget (See the definition of auto-wrapped widgets above).
This means
my $tab = $mw->BLTNoteBook;
will create blt::tabnotebook widget. Effectively, this is equivalent to the following Tcl/Tk code:
package require BLT # but invoked only once
blt::tabnotebook .bltnbook1
After the above example code, the variable $tab
is a Tcl::pTk::Widget that behaves in the usual way, for example:
$tab->insert('end', -text=>'text');
$tab->tabConfigure(0, -window=>$tab->Label(-text=>'text of label'));
These two lines are the Tcl/Tk equivalent of:
.bltnbook1 insert end -text {text}
.bltnbook1 tab configure 0 -window [label .bltnbook1.lab1 -text {text of label}]
You can also intermix the perl/tk and Tcl/Tk syntax like this:
$interp->Eval('package require BLT;blt::tabnotebook .bltnbook1');
$tab = $interp->widget('.bltnbook1');
$tab->tabConfigure(0, -window=>$tab->Label(-text=>'text of label'));
How to read Tcl/Tk widget docs when using in Tcl::pTk
For the documentation of standard perl/tk widgets (like Button, Entry, Menu, etc), you can refer to the the perl/tk docs Tk (We may move a copy of the perl/tk docs to Tcl::pTk in the future). For non-standard widgets (like the BLTNotebook widget example above) you have to use the Tcl docs on the widget for the widget documentation. (Most Tcl/Tk docs can be found at http://www.tcl.tk/ )
When reading Tcl/Tk widget documentation about widgets, you can apply the following guidelines to determine how to use the widget in Tcl::pTk
using perl/tk syntax.
Suppose the Tcl/Tk docs say:
pathName method-name optional-parameters
(some description)
This means the widget has a has method method-name
and you can invoke it in Tcl::pTk
like
$widget->method-name(optional-parameters);
The $widget
variable in Tcl::pTk
is like the pathName in the Tcl/Tk docs.
Sometimes the Tcl/Tk method-name consists of two words (verb1 verb2). In this case there are two equivalent ways to invoke it, $widget->verb1('verb2',...);
or $widget->verb1Verb2(...);
.
Widget options are used just like they are shown in the Tcl/Tk docs. There is no special translation needed for the widget options described in the Tcl/Tk docs for use in Tcl::pTk
.
Miscellaneous methods
$int->widget( path, widget-type )
When widgets are created in Tcl::pTk
they are stored internally and can be retrieved by the widget()
method, which takes widget path as first parameter, and optionally the widget type (such as Button, or Text etc.). For Example:
# this will retrieve widget, and then call configure on it
widget(".fram.butt")->configure(-text=>"new text");
# this will retrieve widget as Button (Tcl::pTk::Button object)
my $button = widget(".fram.butt", 'Button');
# same but retrieved widget considered as general widget, without
# specifying its type. This will make it a generic Tcl::pTk::Widget object
my $button = widget(".fram.butt");
Please note that this method will return to you a widget object even if it was not created within Tcl::pTk
. A check is not performed to see if a widget with given path name exists. This enables the use of widgets created elsewhere in Tcl/Tk to be treated like Tcl::pTk
widgets.
widget_data
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';
Note:
Use of this method has largely been superceded by the perl/tk-compatible privateData
widget method.
$widget->tooltip("text")
Any widget accepts the tooltip
method, accepting any text as parameter, which will be used as floating help text explaining the widget. The widget itself is returned, so to provide convenient way of chaining:
$mw->Button(-text=>"button 1")->tooltip("This is a button, m-kay")->pack;
$mw->Entry(-textvariable=>\my $e)->tooltip("enter the text here, m-kay")->pack;
The tooltip
method uses the tooltip
package, which is a part of tklib
within Tcl/Tk, so be sure you have that Tcl/Tk package installed.
Note: The perl/tk-compatible Balloon widget is also available for installing tool-tips on widgets and widget-elements.
Terminology
In the documentation and comments for this package, perl/Tk, Tcl/Tk, Tcl::pTk, Tcl.pm, and Tcl are used. These terms have the following meanings in the context of this package.
- perl/Tk
-
The traditional perl interface to the Tk GUI libraries. i.e the perl package occupying the Tk namespace on CPAN.
- Tcl/Tk
-
The Tcl/Tk package with tcl-code and associated libraries (e.g. Tcl.so or Tcl.dll and associated tcl-code). See http://www.tcl.tk/
- Tcl::pTk
-
This package, which provides a perl interface into the Tcl/Tk GUI libraries.
- Tcl.pm
-
The Tcl perl package, which provides a simple interface from perl to Tcl/Tk. Tcl::pTk interpreter objects are subclassed from the Tcl package.
- Tcl
-
The Tcl programming language.
BUGS
Currently work is in progress, and some features could change in future versions.
AUTHORS
- Malcolm Beattie.
- Vadim Konovalov, vadim_tcltk@vkonovalov.ru 19 May 2003.
- Jeff Hobbs, jeffh _a_ activestate com, February 2004.
- Gisle Aas, gisle _a_ activestate . com, 14 Apr 2004.
- John Cerney, john.cerney _a_ gmail . com, 29 Sep 2009.
- Christopher A. Chavez, chrischavez _a_ gmx . us, May 2018.
COPYRIGHT
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