Dynamically creating gui objects on demand in Perl
I've been working on my project for learning perl Gui programming. What I want to do is create a Gui interface for Linux commands. Not because I think there's any need for such a thing but just because I think it provides a good base for learning Perl. It's not meant to be production software but maybe I can turn it in to a learning tool for linux commands or something.
Previously..
In my previous article I described how I created a Window with a text block and how to show the output of the "ls" command (I made it as simple as possible on purpose, I know there are easier ways to execute the ls command).
Dynamic checkbox creation
I also created a box which contained checkboxes for a few of the options of the ls command. As I want to add more commands to the tool it would take me a lot of time to create all the checkboxes and a lot of copy pasting code. I don't think that's a good idea, so I've been thinking of some way of dynamically creating vertical boxes containing the checkboxes for all options per command. That way I can just create a VBOX by passing a command and it's options to a subroutine.
Object orientation
This is possible because the Gtk library is object oriented, so I can create objects in my subroutine and pass them back. I think I'm going to do something like subclassing the Vbox class in the future, at this moment I don't have a clue how to accomplish such a thing. For now I'll just start with some kind of proof of concept code. In my previous article I got to version 7 of the program so here I'll start with version 8.
2 Dimensional array
In this version I add a 2 dimensional array which is going to contain arrays of command options, this is not needed for this version as here I'll only use 2 commands and I know upfront it are only 2 commands. I want the program to be flexible so it will be easy to add any number of commands with their respective options without changing the code. That's why I want to use a 2 dimensional array, I want to be able to add anonymous arrays for every option dynamically.
Option hash
I also add a hash which contains key=>value pairs for a list of command options, this is only for testing purposes and I think I will try to read this information from a file in a future version.
A new Box
I also created a third Box which is the result of calling a subroutine with the previously created hash as argument.
my $box3 = &selectBoxCreator(%optionHash);
This creates a VBox which I later add to the HBox I can create as many boxes as I like this way, for example if I would create another hash containing all the options for the rm command, I could just pass the hash to the selectBoxCreator and I get back a new VBox which I can in turn add to the HBox.
Sub for dynamic Box creation
To accomplish this I added a sub to the code which creates a VBOX
# our new subroutine for creating a VBOX containing multiple checkboxes dynamically created from a hash
sub selectBoxCreator
{
#the %optionHash contians all our options with their description
my %options = @_;
#the new VBOX object
my $newVBOX = Gtk2::VBox->new(FALSE, 0);
#run a sub as many times as there are key,value pairs
#$key and $value are filled with the $key=>$value pairs
#for each step
while ( my ($key, $value) = each(%options) )
{
# I tried to do this in one sub, but that didn't work
# So I created a sub checkboxFactory
# I think it's because the anonymous sub for the toggled signal
# is created in another scope this way
# Therefore we get multiple anonymous subs
# If I create everything here the sub is just reassigned
# (that's my guess anyway, I'm just starting to learn this stuff)
#here we create a new checkbox
my $btnNew = &checkboxFactory($value,$key);
#and pack it into our new VBOX
$newVBOX->pack_start($btnNew, FALSE, FALSE, 0)
}
return $newVBOX;
}
Sub for dynamic checkbox creation
And another sub needed for creation of the checkboxes
I get the value and the key which are passed from the call with shift, create a new checkbox with value as argument
value is the secription of the option.
In the anonymous sub I connect to the button I dereference the reference to the 2 dimensional array to get an array again.
I no it looks ugly, I hope there is a more readable way to do this, I couldn't get it to work in any other way. It seems we can only create a multi dimensional array using references and we can only push into arrays not into references. If anybody can show me a better way, please do so.
sub checkboxFactory
{
my $value = shift @_; # gets the firtst argument
my $key = shift @_; # gets the second argument
my $index; # create a index variable which is only ever seen by this checkbox, every checkbox has it's own
my $btn = Gtk2::CheckButton->new($value); # create a new Gtk checkbutton
$btn->show; # set it visible
#connect a sub to the toggled signal of this box
#this sub is anonymous so we can recreate it everytime
$btn->signal_connect('toggled' =>sub
{
if($btn->get_active)
{
#push returns new array lenght
#from inside to out $arrayMatrix is a reference that contains array references
#@{$arrayMatrix} dereferences $arrayMatrix to an array of references
#@{@{$arrayMatrix}[0]} dereferences the array reference on position 0 of
#@{$arrayMatrix} to an array of values
# to which we push our $key, returning a new array size
#test if $index has been filled before if not use push
#to push the $key to the end of the array
if (!defined $index){
$index=push (@{@{$arrayMatrix}[0]},$key);}
#in the other case there is an index for this option
#then this sub has run before
else {$arrayMatrix->[0][$index-1]=$key};
print @{$arrayMatrix->[0]};
}
else
#this part is run when the checkbox is unchecked
{
#remove the option from the array
$arrayMatrix->[0][$index-1]="";
print @{$arrayMatrix->[0]};
&textViewUpdate;
}
}
);
return $btn;
That's it for today I uploaded the code here:
http://www.handlewithlinux.com/downloads/code/commandViewerStep8.tar.gz
or read it online here:
http://www.handlewithlinux.com/downloads/code/commandViewerStep8
Read it in eclipse that's easier than online. I added a lot of comments to the code so it's a bit understandable.
It surprised me once again how easy to understand Perl can be, it really is a great language. I did encounter some difficulties understanding this reference and dereference stuff. But that's more accountable to my wishes than to the complexity of the language I guess.
If anybody knows a better way to accomplish what I did here. Please leave a comment.
Coming up:
In my next article I'll remove the static block of checkboxes and replace it with a dynamically changed box according to a selectbox. I'm thinking of adding a box to give a text to the command (like ls-l /usr/bin)
I'll see how far I get. I'm planning to rewrite this code to object oriented code, but I need to learn some more before that.
This is the seventh article in an ongoing series about learning Perl GUI programming.Find the other articles here:
1. starting perl GUI programming
2. Installing Eclipse, the Epic Perl plugin and my first Perl GUI program
3. Open Source rocks! Learning from code by debugging
4. Quick and dirty linux GUI programming
5. resources for learning Perl Graphical Programming
6. Drawing and animating directly to the Desktop with Perl
7. Dynamically-creating-gui-objects-on-demand-in-Perl
Popular content
Recent blog posts
- HP linux netbook
- Toshiba Android netbook
- android video terminal
- rugged android phone
- Linux PC Robot < 500$ DIY Linux robot
- Q7 Linux MID nice but missing most important feature
- BD remote for android available soon
- Intelligent Linux based scriptable network camera
- Edge the first foldable dual screen ebook reader/netbook
- iPed chinese for iPad
don't forget to vote if you find something useful!!
- More things that Linux makes easy
9 weeks 13 hours ago - It looks rather like
10 weeks 2 days ago - Performance will be mediocre...
11 weeks 1 day ago - Off-base & Totally Terrible Review
11 weeks 3 days ago - suicidal robot bomber ?
11 weeks 3 days ago - Not a missing feature dumbass!
11 weeks 3 days ago - Impractical device
11 weeks 6 days ago - posting from my edge...
12 weeks 22 hours ago - Yes, running Android makes it expandable.
12 weeks 1 day ago - I have an edge and it is excellent
12 weeks 1 day ago
Navigation
Linux systeembeheer
Linux server

Smallest Linux PC, smaller
than an apple

Linux home automation

Electrical superbike
powered by Linux

Coolest Linux robot ever
transforming,camera,
remote control

Samsung tv Linux hack

Linux multimedia
dream machine

More cool stuff
like this solid gold macbook
at criticalcold.com
Tags
Best karma users
- kaikokan
- uioloio
- martha23
- jake
- j00p34
Categories



What's the point?
Anonymous 1 year 11 weeks 5 days 23 hours ago
I suppose you can see a point. in 2009, to learning Perl.
I can't.
why not?
kaikokan 1 year 11 weeks 5 days 11 hours ago
It's used a lot on Linux and Perl programmers make more money than PHP programmers ;-)
"I added a lot of comments to the code so it's a bit understand"
Anonymous 1 year 11 weeks 6 days 2 hours ago
Proper indention helps quite a bit as well ;)
try the gziped version
kaikokan 1 year 11 weeks 5 days 11 hours ago
The indentation is removed by the site, the download has it.
But you are right about that