The Practical Programming in Script Based Graphics User Interface
Menu Menu
Self Introduction
kono@ie.u-ryukyu.ac.jphttp://rananim.ie.u-ryukyu.ac.jp
Associate Professor of University of the Ryukyus ('96-)
Sony Computer Science Laboratory, Inc. ('89-'95)
Phd. The university of Tokyo, Information Engineering
Research Area
Temporal Logic, Object Oriented Programming, Concurrent Object, Program Verificaiton, Network Programming
Script Language
Shell Awk Perl Ruby HTML/SHTML
Advantage of Script Language
Quick Visible Network Transparent High Portability Easy to modify
Disadvantage of Script Language
Slow No hidden source High Portability Easy to modify
Perl
Unix Culture Oriented No adhoc limitation on data size String manipulation Dynamic Extendable Array Associatibe Array Object Orientation
Target of Perl
CGI (WWW page generator) Log processing ( login record, etc. ) Database Proprocessing of large data Data conversion GUI application
What is Unix Culture
Flat text Combination of Command Tools File descriptor stdin, stdout, stderr pipe, redirect, socket
Programming Perl
Similarity Sh, Csh, Awk, C
Programming Perl (conditional)
1. if ($i++ <10 ) { print $i; }2. print $i if ($i++ <10 );3. print $i unless ($i++ > 9 );4. open(FD,"<test") || die("error $@\n");5. open(FD,"<test") or die("error $@\n");
Programming Perl (control)
1. while(<>) { $i++; }; print $i;2. print $_ while(<>);3. while(<>) { print $_; last if ($i++ > 10); }4. while(<>) { next if ($i++ < 10); print $_; last if ($i++ > 20); }5. while(<>) { print if (10..20); }6. do { print "$i\n"; } until($i++ < 10) ;
sub gcd0 {my ($a,$b) = @_; return ($a > $b) ? $a % $b : $b % $a;}
Ex. complete a program which calculate GCD.
Perl Data Types
Perl's variables are prefixed by one character type description.Character | Type |
$a | scalar (0 dimention value) |
@a | entire array, vector(1 dimention value) |
$a[1] | value of an element of the array (scalar) |
%a | entire associative array |
$a{1} | value of an element of the associative array |
<a> | File handle |
&a | procedure |
\$a | reference |
$$a | value of reference |
() | list |
[] | anonymous array |
{} | anonymous associative array |
-- | boolean if(), while() |
Perl document
perldoc -f builtin-function
Debugging Perl
perl -de 0
Quick and easy programming
Even if we use script language, we have to program clearly.
Perl programming (pattern)
defined($var) | variable $var is defined | |
$var | $var is defined and neither 0 or "" | |
$a == $b | equal numerically | |
$a != $b | not equal numerically | |
$a > $b | numerically large | |
$a eq $b | equal literally | |
$a ne $b | not equal literally | |
$a =~ /pattern/ | pattern match | |
$a =~ s/pattern/replace/ | substitution |
if $var is ommited, defualt variable $_ is used. In while(<>), $_ is automatically set from current file handle.$var =~ /pattern/; $var =~ s/pattern/replace/;
orwhile(<>) { if (/pattern/) { print; } }
is the same as grep command in Unix./pattern/ && print while (<>);
Perl programming (regular expression)
ABCD | Literal string | |
[a-z] | raging from a to z | |
[a-z]* | 0 or more repeated range | |
[a-z]+ | 1 or more repeated range | |
. | arbitrary character except new line | |
(ABCD)+ | repeated word pattern | |
$var | $var itself | |
\W | predefine word class | |
\{ | special character |
s/j980(\d\d)/& = $1/;
Perl programming (Reference)
pw071: {1} % perl5 -de 0Understnad reference in examples below.Loading DB routines from perl5db.pl version 1 Emacs support available.
Enter h or `h h' for help.
main::(-e:1): 0
DB<1> @a = (1,2,3,4,5) DB<2> p "@a"1 2 3 4 5DB<3> @b = @a DB<4> p "@b"1 2 3 4 5DB<5> $a[2]="kono" DB<6> p "@a"1 2 kono 4 5DB<7> p "@b"1 2 3 4 5DB<8> $a = [1,2,3,4,5] DB<9> p $aARRAY(0x805b3b4)DB<10> p @$a12345DB<11> p "@$a"1 2 3 4 5DB<12> $$a[1] = "kono" DB<13> p "@$a"1 kono 3 4 5DB<14> $b = $a DB<15> $$b[2] = "kakazu" DB<16> p "@$b"1 kono kakazu 4 5DB<17> p $bARRAY(0x805b3b4)DB<18> p $b->[2] = "higa"higaDB<19> p "@$b"1 kono higa 4 5DB<20> $c = {} DB<21> $c->{'kono'} = 'teacher' DB<22> $c->{'higa'} = 'student' DB<23> p %$chigastudentkonoteacherDB<24> $c{'kono'} = 1 DB<25> $c{'higa'} = 2 DB<26> p keys %chigakonoDB<27> p $cHASH(0x8134cc0)
DB<28> $d = \%c DB<29> p $dHASH(0x8152b00)DB<30> $d->{'shimabukuro'} = 'student' DB<31> p keys %chigashimabukurokonoDB<32>
Ex. Try following examples.
$a=[1,2,3,4]; $a->[5]=3; print "@$a, $a->[2]\n"; $b={}; $b->{First}='Cat'; $b->{Second}='Dog'; $b->{Third}='Pig'; foreach $key ( keys %$b) { print "$key is $b->{$key}\n" }
@a = ( 1,2,3,4); $refa = \@a; $refa->[5]=3; print "@$refa, $refa->[2]\n";
The Practice of Programming
Brian W. Kerninghan, Rob Pike 1999, Adison-Wesley.There are good old books,
The Elements of Programming Style, 1978 Software Tools, Adison-Wesley, 1976(based on fortran))
Performance of languages
</td><td> 250MHz <br> R10000</td><td> 400MHz <br> Pentinum II</td><td> Lines of <br> source code | |||
c | 0.36sec | 0.30sec | 150 |
Java | 4.9 | 9.2 | 105 |
C++/dequeue | 2.6 | 11.2 | 70 |
C++/list | 1.7 | 1.5 | 70 |
Awk | 2.2 | 2.1 | 20 |
Perl | 1.8 | 1.0 | 18 |
Perl Module
Find.pm
Perl Object
Object = Data + Module
package Mammal;
sub new {
my $type = shift; my %params = @_; my $self = {}; $self->{'Name'} = $params{'Name'}; $self->{'Sex'} = $params{'Sex'}; $self->{'Weight'} = $params{'Weight'}; $self->{'Color'} = $params{'Color'}; bless $self, $type;}package Cat;
@ISA = qw( Mammal );
sub new {
my $type = shift; my %params = @_; my $self = Mammal->new(@_); $self->{'Character'} = $params{'Character'}; bless $self, $type;}# method
sub miyao { my ($self,$arg) = @_; $self->{Name} = $arg; } sub name_print { my ($self) = @_; print $self->{Name}; print "\n";}# Usage
$a = Cat->new(Name=> Jackey, Sex=>F); print $a->{Name};print "\n"; $a->name_print;
CPAN
The CPAN </a> contains the collected wisdom of the entire Perl community:hundreds of Perl utilities, several books' worth of documentation, and the entire Perl distribution. If it's written in Perl, and it's helpful and free, it's in the CPAN.
Perl/Tk
Tk library Separation of GUI and main program Combination
Traffic Singal in Perl/Tk
Write a traffic signal in Perl/Tk.
This program is executed in this way.package Signal; sub new { my $type = shift; my %params = @_; my $self = {}; $self->{'State'} = $params{'State'}; $self->{'State'} = defined($params{'State'})? $params{'State'}:'red'; $self->{'States'} = ['green','yellow','red']; bless $self; } sub next { my ($self) = shift; my $state = $self->{'State'}; if($state eq 'red') { $self->{'State'} = 'green'; } elsif($state eq 'green') { $self->{'State'} = 'yellow'; } else { $self->{'State'} = 'red'; # Red for all other cases } # return $self->{'State'}; } sub print { my ($self) = shift; my $state = $self->{'State'}; print $state; }
DB<3> $a = Signal->new(State=>Red); DB<4> $a->print DB<5> $a->next DB<6> $a->print red DB<7> $a->next DB<8> $a->print green
Perl/Tk (main)
Perl/Tk では、MainWindow を作り、そこに、いろいろなwidgetをpack していく。とすれば、MainWindowができる。MainWindowのインスタンスとして、いろいろなものを使うことができる。my $main = MainWindow->new();
Label | 文字を印として置く |
Text | 編集用のテキスト |
Entry | 入力カラム |
Canvas | 図形表示 |
Frame | いくつかのwidgetをまとめる |
Canvas とタグ
Canvasには以下のような図を書くことができる。
oval | 楕円 |
rectangle | 箱 |
line | 線 |
polygon | 多角形 |
bitmap | イメージ |
text | テキスト |
$canv->move($ball, $deltax, $deltay); | 移動 |
$canvas->itemconfigure($view,-fill=>'black'); | 色などの変更 |
$canvas->delete($view); | 削除 |
信号機を表示する<a > Perl/Tkのプログラム</a>は以下のようになる。
この方法では、信号は自動的に点滅するという感じではない。そのためには、after という機能を使うことができる。package SignalView; use Tk; sub new { my $type = shift; my %params = @_; my $self = {}; my $signal = Signal->new(%params); my $main = $params{-main}; my $canvas; my $states = $signal->{'States'}; my %views = (); if(! defined( $main)) { $main = MainWindow->new(%params); } $canvas = $main->Canvas(-width=>50,-height=>150); $x = 5; $y = 5; $r = 40; for $state ( @$states ) { $views{$state} = $canvas->create('oval', $x, $y, $x+$r, $y+$r, -width => 1, -outline => 'black', -fill => 'black'); $y += 50; } $canvas->pack(); $self->{'MainWindow'} = $main; $self->{'Canvas'} = $canvas; $self->{'Views'} = \%views; $self->{'Signal'} = $signal; bless $self; } sub next { my ($self) = shift; my $state = $self->{'Signal'}->{'State'}; my $view = $self->{'Views'}->{$state}; my $canvas = $self->{'Canvas'}; $canvas->itemconfigure($view,-fill=>'black'); $state = $self->{'Signal'}->next(); $view = $self->{'Views'}->{$state}; $canvas->itemconfigure($view,-fill=>$state); } sub update { my ($self) = shift; $self->{'MainWindow'}->update(); } package Main; $signal = SignalView->new(); $signal->update(); while($i++<100) { $signal->next(); $signal->{'Signal'}->print(); print "\n"; $signal->update(); sleep(1); }
package MainWindow; sub Signal { my ($self) = shift; return SignalView->new(-main=>$self); } package SignalView; sub new { my $type = shift; my %params = @_; my $self = {}; my $signal = Signal->new(%params); my $main = $params{-main}; my $canvas; my $states = $signal->{'States'}; my %views = (); $self->{'Interval'} = 500; $canvas = $main->Canvas(-width=>50,-height=>150); $x = 5; $y = 5; $r = 40; for $state ( @$states ) { $views{$state} = $canvas->create('oval', $x, $y, $x+$r, $y+$r, -width => 1, -outline => 'black', -fill => 'black'); $y += 50; } $canvas->pack(-side=>left); $self->{'MainWindow'} = $main; $self->{'Canvas'} = $canvas; $self->{'Views'} = \%views; $self->{'Signal'} = $signal; bless $self; } sub next { my ($self) = shift; my $state = $self->{'Signal'}->{'State'}; my $view = $self->{'Views'}->{$state}; my $canvas = $self->{'Canvas'}; $canvas->itemconfigure($view,-fill=>'black'); $state = $self->{'Signal'}->next(); $view = $self->{'Views'}->{$state}; $canvas->itemconfigure($view,-fill=>$state); } sub update { my ($self) = shift; $self->{'MainWindow'}->update(); } sub run { my ($self) = shift; my %params = @_; my $main=$self->{'MainWindow'}; if(defined($params{'Interval'})) { $self->{'Interval'} = $params{'Interval'}; } if(! $self->{'Running'}) { $self->{'Running'} = 1; $main->after($self->{'Interval'},sub {$self->running()}); } } sub running { my ($self) = shift; my $interval = $self->{'Interval'}; if($self->{'Running'}) { $self->next(); $self->update(); $self->{'MainWindow'}->after($interval,sub {$self->running()}); } } sub stop { my ($self) = shift; $self->{'Running'} = 0; } package Main; use Tk; $main = MainWindow->new(); $signal = $main->Signal(); $signal->run(); &MainLoop();
Call Back と Controller
この信号をさらに外から制御するには、controller をViewに付加する。
ボタンからの情報を処理するにはCall Backを使う。Call Back では、Call Back する先を、my 変数により保持する。これをClosure という。オブジェクトを使っても同じことが実現できるが、Closureの方が構文的には軽い。
package SingalView; sub controller { my ($self) = shift; my $main=$self->{'MainWindow'}; # my $c= $main->Toplevel(); my $c= $main->Frame(); my $int= $c->Frame(); my $int_entry = $int->Entry(-relief => 'sunken',-width=>5); my $int_label= $int->Label(-text=>"Interval:"); my $quit = $c->Button( -text => 'Quit', -width => 10, -command => sub {$main->destroy}); my $run = $c->Button( -text => 'Run', -width => 10, -command => sub { $self->run(Interval=>($int_entry->get())) } ); my $stop = $c->Button( -text => 'Stop', -width => 10, -command => sub {$self->stop}); $int->pack(-side => 'top', -fill => 'x'); $int_entry->pack(-side => 'right'); $int_label->pack(-side => 'left'); $c->pack( -side => 'right', -expand => 'no', -pady => 2); $int->pack(-side => 'top', -expand => 'no', -pady => 2); $run->pack( -side => 'top', -expand => 'no', -pady => 2); $stop->pack(-side => 'top', -expand => 'no', -pady => 2); $quit->pack(-side => 'top', -expand => 'no', -pady => 2); # set default value $int_entry->insert(0,$self->{'Interval'}); $self->{'Controller'}=$c; $self->update(); } # end