Tcl::pTk - Interface to Tcl/Tk with Perl/Tk compatible sytax
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;
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.
Tcl::pTk
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).
Tile
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;" to "Use 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+
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.
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.
Tcl::Tk
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.
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 my the call to the MainWindow (or tkinit) methods, but can also be created explicitly.
MainWindow
tkinit
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)
my $int = new Tcl::pTk(":5");
Perl/Tk compatible syntax:
MainLoop; # Exact same syntax used as perl/Tk
Tcl::pTk Syntax:
$inst->MainLoop;
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.
$widget->method
Direct access using Eval-ed Tcl code. (e.g. using the Eval Tcl::pTk method)
Eval
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.
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.
$int->Eval('...')
The Tcl Interpreter
The Tcl interpreter is used to process Tcl/Tk widgets; within Tcl::pTk you create it with new, and given any widget object, you can retreive it by the $widget->interp method. ( Within pure Tcl/Tk the interpreter already exists, you don't need to create it explicitly. )
new
$widget->interp
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 it butt, then you should specify name .fram.butt. Widget paths are also refered in other miscellaneous widget operations, like geometry management.
.fram
butt
.fram.butt
At any time a widget's path can be retreived with $widget->path; within Tcl::pTk.
$widget->path;
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.
.fr.b
$int->Eval('.fr.b configure -text {new text}');
$button->configure(-text=>'new text');
$button
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 it's path on the interpreter.
use Tcl::pTk;
Tcl::pTk::Widget
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.
Button
Frame
Text
Canvas
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).
$label
Tcl::pTk::Label
Tcl::pTk Widgets fall into the following basic categories, based on how they are implemented in the Tcl::pTk package.
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.
$button-
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.
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 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.
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
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 package Tcl::pTk::Entry is created, which sets up the class hierarchy for any further Entry widgets. The newly-created Tcl::pTk::Entry class is be a direct subclass of Tcl::pTk::Widget.
entry
Tcl::pTk::Entry
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 package Tcl::pTk::Entry, which will end-up calling calling the invoke method on the Tcl/Tk interpreter (i.e. $entry-interp()->invoke($entry, 'insert', -text, 'text')
insert
$entry
invoke
$entry-
The first time insert is called, the insert method does not exist, so AUTOLOAD comes into play and creates the method. The second time insert is called, the already-created method is called directly (i.e. not created again), thus saving execution time.
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 a Tcl::pTk::Text package already exists, a new package is not created at runtime like the case above.
text
Tcl::pTk::Text
The second code line above calls the insert of the $text object of type Tcl::pTk::Text. This insert method is already defined in the Tcl::pTk::Text package, so it is called directly.
$text
The third code line above calls the markNames method on the $text object. This method is not defined in the Tcl::pTk::Text package, so the first time when makrNames is called, AUTOLOAD in the Tcl::pTk package comes into play and creates the method. The second time makkNames is called, the already-created method is called directly (i.e. not created again), thus saving execution time.
markNames
makrNames
makkNames
Suppose $widget isa Tcl::pTk::Widget, its path is .path, and method method invoked on it with a list of parameters, @parameters:
$widget
.path
method
@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:
$method
m/^[a-z]$/
.path method parameter1 parameter2 ....
.path method parameter1 parameter2
tagNames
m/^[a-z]+[A-Z][a-z]+$/
.path method submethod parameter1 parameter2 ....
.path method submethod parameter1 parameter2
methodSubmethSubsubmeth
.path method submeth subsubmeth parameter1 parameter2 ....
.path method submeth subsubmeth parameter1 parameter2
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.
_
$text-
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.
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.
Declare
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 equavalent 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
$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'));
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
method-name
$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-
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.
$int->widget( path, widget-type )
When widgets are created in Tcl::pTk they are stored internally and can and can be retreived by the widget() method, which takes widget path as first parameter, and optionally the widget type (such as Button, or Text etc.). For Example:
widget()
# 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.
privateData
$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:
tooltip
$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.
tklib
Note: The perl/tk-compatible Balloon widget is also available for installing tool-tips on widgets and widget-elements.
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.
The traditional perl interface to the Tk GUI libraries. i.e the perl package occupying the Tk namespace on CPAN.
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/
This package, which provides a perl interface into the Tcl/Tk GUI libraries.
The Tcl perl package, which provides a simple interface from perl to Tcl/Tk. Tcl::pTk interpreter objects are subclassed from the Tcl package.
The Tcl programming language.
Currently work is in progress, and some features could change in future versions.
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
To install Tcl::pTk, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Tcl::pTk
CPAN shell
perl -MCPAN -e shell install Tcl::pTk
For more information on module installation, please visit the detailed CPAN module installation guide.