Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Tk and Object Oriented Programming

by mortis (Pilgrim)
on Nov 20, 2001 at 06:32 UTC ( [id://126460]=perlmeditation: print w/replies, xml ) Need Help??

Tk makes heavy use of callbacks. In Perl, this basicly means anonymous subroutines. Most of the example code you see for Perl/Tk takes a procedural approach. For the callback for a button, you often see code like:

use strict; use warnings; use Tk; my $mw = Tk::MainWindow->new(); $mw->Button( -text => "Exit", -command => sub { $mw->destroy(); } )->pack(); # or $mw->Button( -text => "Exit", -command => \&pressExitButton )->pack(); MainLoop(); sub pressExitButton { $mw->destroy(); }

Unfortunatly, even in the above example, this leads to either using lots of globals (like $mw in the example above), or having to pass an ever growing list of arguments to each of your functions. I tend to like object oriented code, and I feel that this technique doesn't promote encapsulation.

I doubt I'm the first person to come up with this, but I hit on the idea of calling methods from the anonymous subs passed to Tk for the callbacks:

package MyGui; use strict; use warnings; use Tk; sub new { my $this = shift; my $class = ref($this) || $this; my $self = {}; bless $self,$class; $self->buildInterface(); return $self; } sub buildInterface { my($self) = @_; my $mw = $self->_mainWindow( Tk::MainWindow->new() ); $self->_exitButton( $mw->Button( -text => "Exit", -command => sub { $self->pressExitButton(@_); } ) )->pack(); return 1; } sub pressExitButton { my($self) = @_; $self->_mainWindow()->destroy(); } sub run { my($self) = @_; MainLoop(); } sub _mainWindow { my($self,$arg) = @_; if($arg) { $self->{'_mainWindow'} = $arg; } return $self->{'_mainWindow'}; } sub _exitButton { my($self,$arg) = @_; if($arg) { $self->{'_exitButton'} = $arg; } return $self->{'_exitButton'}; } 1; package main; MyGui->new()->run();

This keeps the code from having to rely on globals, or long argument lists. The code in this example is a bit more verbose as an object, but illustrates the technique. Following a policy of only calling object methods from the callbacks makes it easier to write encapsulated code. For an application I had to write, this technique even scaled up to support the MDI (multiple document interface) paradigm. It helped us create independant, re-useable components on the project.

The only issues I ever ran into using this related to the support of drag and drop in each of the views in the MDI application. Only one event handler for the drop event would work - the first view that was created had a working drop handler, the rest all ended up calling the event handler from the first view. We worked around this by storing the current view in the application and referencing the current view from within the event handler (this techniuque even made the work around easier to implement).

Has anyone else used this kind of technique before? What has your experience been?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://126460]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (8)
As of 2024-03-28 09:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found