GUI di X dengan Perl/Tk


GUI di X dengan Perl/Tk

Ada beberapa macam cara untuk menulis aplikasi GUI (Graphical User Interface) di X Window, yaitu dengan menggunakan Xlib API, X Toolkit Intrinsic, atau menggunakan salah satu dari GUI toolkit seperti Qt, GTK+, OSF/Motif, dan Tk. Tulisan ini membahas sedikit mengenai pemrograman GUI dengan Perl dan toolkit Tk.



Distribusi-distribusi X Window, seperti misalkan XFree86, menyertakan Xlib API (Application Programming Interface) dan X Toolkit Intrinsic untuk keperluan pengembangan, namun pemrograman menggunakan Xlib sangat merepotkan karena banyak sekali detil tingkat rendah yang perlu dikontrol langsung oleh kode aplikasi. Sementara itu X Toolkit intrinsic atau Xt, yang satu tingkat di atas Xlib juga masih terlalu sulit untuk langsung dipakai membuat aplikasi GUI, dan biasanya Xt digunakan untuk membangun GUI toolkit. Beberapa toolkit yang sangat populer antara lain adalah MIT Athena Widget, OSF/Motif ataupun lesstif [1], Qt [2], GTK+ [3], dan Tk [4].

Toolkit-toolkit demikian menyediakan apa yang disebut sebagai widget, yaitu obyek user-interface seperti button, scrollbar, listbox, checkbutton, radiobutton, label, text, dan lain sebagainya. Widget mengenkapsulasi detil implementasi, dan untuk setiap widget juga sudah didefinisikan perilaku defaultnya, sehingga programmer dapat lebih berkonsentrasi pada logika aplikasinya. Dengan abstraksi tingkat tinggi seperti ini, pemakaian toolkit jauh lebih memudahkan pemrograman GUI.

Tk dan Perl/Tk

Toolkit biasanya dibuat sebagai library C yang independen, sehingga setiap bahasa yang mendukung interfacing ke C akan dapat memanfaatkannya. Sebagai contoh, skrip Perl dapat menggunakan Qt melalui modul PerlQt [5], dan GTK+ melalui modul Gtk-Perl [6]. Sayangnya tidak demikian halnya dengan Tk, karena toolkit yang satu ini bergantung pada bahasa Tcl. Solusi dari Nick Ing-Simmons [7] adalah dengan "mengeluarkan" Tk dari Tcl, sehingga diperoleh Tk yang independen, yang disebut dengan pTk (portable Tk). Tidak berhenti sampai di situ, Nick juga membuat antarmuka berorientasi objek dari Perl ke pTk ini, yaitu Perl/Tk [8].

Pemrograman Perl/Tk sangatlah luas, dan mengikuti tradisi Perl, distribusi Perl/Tk dilengkapi dengan dokumentasi (manual) yang sangat lengkap, disertai banyak contoh.

Di samping itu, juga dapat diperoleh FAQ (Frequently Asked Questions)-nya di CPAN [9], dan dukungan dari komunitas penggunanya melalui mailing list [10].

Tulisan ini hanya membahas beberapa hal dasar yang perlu dipahami untuk membuat aplikasi GUI, yaitu struktur aplikasi Perl/Tk, geometry manager, menu, dan event binding. Macam-macam class widget tidak dibahas satu persatu, namun diberikan contoh pembuatan aplikasi yang GUI-intensive, yaitu clone dari game jigsaw puzzle dari WindowsEntertainmentPack. Contoh disertai pembahasan sebuah aplikasi yang utuh seperti ini diharapkan lebih bermanfaat daripada contoh-contoh kode pemakaian widget, yang selain dapat dipelajari dari manual masing-masing widget juga dapat diperoleh dari FAQ dan distribusi Perl/Tk sendiri.

Struktur Aplikasi Perl/Tk

Contoh yang minimal seperti Hello World pada listing 1 membantu kita memahami struktur umum aplikasi-aplikasi Perl/Tk.

1| #!/usr/bin/perl

2| use Tk;

3| $mw = MainWindow->new;

4| $mw->title("Howdy World!");
5| $l = $mw->Label(-text => "Howdy World!");
6| $b = $mw->Button(-text => "Exit", -command => sub { exit });
7| $l->pack;
8| $b->pack;
9| MainLoop;
Listing 1. hello

Seperti biasa, baris 1 memanggil interpreter Perl, sedangkan baris 2 memuat modul Tk.

Baris 3 menciptakan window MainWindow yang kemudian disimpan ke dalam variabel $mw, dan baris 4 mengeset title-nya. Window MainWindow adalah window yang pertama diciptakan dalam aplikasi, dan bertindak sebagai parent bagi widget-widget yang diciptakan kemudian dalam aplikasi yang sama. Dalam contoh di atas, baris 5 menciptakan widgetLabel ($l), dan baris 6 menciptakan widgetButton ($b) dari $mw sebagai parent-nya, sekaligus mengatur teks yang ditampilkan pada masing-masing widget dengan opsi -text.

Agar dapat berinteraksi dengan user, aplikasi harus dapat merespon event-event yang dibangkitkan sebagai hasil dari aksi user pada widget tertentu, misalkan kombinasi penekanan tombol Alt dan O, klik tombol kiri mouse, gerakan mouse, dan lain sebagainya. Untuk melakukan ini, maka event pada widget tertentu perlu diasosiasikan dengan subrutin yang ditulis sebagai handler event tersebut. Langkah ini disebut dengan event binding. Baris 6 melakukan event binding pada $b dengan menggunakan opsi -command. Dengan opsi ini, subrutin yang didaftarkan akan dipanggil pada saat aplikasi menerima event tombol kiri mouse dilepas di atas widget tersebut. Ada cara lain di mana kita dapat mendefinisikan sendiri event-event yang diharapkan, yaitu dengan method bind() yang akan dijelaskan nanti pada bagian Event Binding.

Baris 7 dan 8 berturut-turut meletakkan $l dan $b dengan methodpack() di atas window $mw. Methodpack() adalah salah satu geometry manager yang berguna untuk menata letak widget-widget di atas sebuah window.

Setelah segala sesuatunya siap, aplikasi harus memantau event-event yang dibangkitkan, dan meneruskannya ke widget yang bersesuaian. Ini dilakukan melalui loop yang disebut dengan event loop. Fungsi Tk::MainLoop menjalankan event loop ini sekaligus menampilkan windowMainWindow ke layar. Baris 9 memanggil fungsi yang diekspor secara default ini.

Secara ringkas, aplikasi-aplikasi Perl/Tk umumnya ditulis sebagai berikut:

1.Buat windowMainWindow,

2.Buat widget-widget lainnya, dan atur tata letaknya menggunakan geometry manager,

3.Event binding,

4.Panggil fungsi MainLoop().

Geometry Manager

Geometry manager diperlukan untuk menata letak dan penampilan widget di atas sebuah window. Di antara macam-macam geometry manager, seperti place(), grid(), pack(), dan form(), pack() adalah yang paling banyak digunakan karena cocok untuk kebutuhan sebagian besar aplikasi.

Untuk mengatur letak widget apakah di bagian atas, kiri, kanan ataupun di bagian bawah window, gunakan opsi -side. Sebagai contoh adalah listing 2, dengan hasil seperti pada Gambar 1.

1| for (qw/left top right bottom/) {

2| $mw->Button(-text => $_,
3| -command => sub { exit } )->pack(
4| -side => $_,
5| );
6| }
Listing 2. pack-ltrb



Method pack() mengalokasikan daerah berbentuk segiempat untuk ditempati widget yang memanggilnya. Daerah ini tidak nampak, dan secara default widget ditempatkan di tengah daerah ini.



Gambar 1. Empat Button dengan -side left, top, right, bottom






Kita dapat membuat widget mengisi daerah alokasi tersebut dengan opsi -fill. Jika pada listing 1 kita tambahkan -fill => 'both' pada opsi pack(), maka keempat widget Button akan memenuhi daerah alokasi tersebut, seperti terlihat pada gambar 2.




Gambar 2. Empat Button Memenuhi Daerah Alokasi






Urutan pemanggilan pack() dengan -side yang berbeda-beda menghasilkan daerah alokasi yang berbeda. Sebagai contoh jika pada listing 1 keempat widget di-pack() dengan urutan -side: top, bottom, left, right, maka hasil yang diperoleh seperti pada gambar 3.

Gambar 3. Empat Button dengan -side top, bottom, left, right



Pedoman yang dapat dipakai di sini adalah pack() berusaha mengalokasikan daerah seluas mungkin bagi widget yang memanggilnya. Untuk -side top dan bottom, ruang yang tersedia dalam arah horisontal akan diambil, sedangkan untuk -side left dan right, ruang pada arah vertikal diambil.

Informasi lengkap mengenai geometry manager dapat dilihat pada manual Tk::pack, Tk::form, Tk::place, dan Tk::grid (untuk membaca manual modul-modul Perl, pada prompt shell ketikkan man diikuti nama modul tersebut, misalkan: man Tk::pack).

Menu

Menu dapat dibuat dengan widget class Menu. Pada listing 3 dapat dilihat contoh pembuatan menu.

1| #!/usr/bin/perl

2| use Tk;

3| $mw = MainWindow->new(-title => "Contoh Menu");

4| $menu = $mw->Menu;

5| $file_m = $menu->cascade(-label => '~File', -tearoff => 0);
6| $opt_m = $menu->cascade(-label => '~Options', -tearoff => 0);
7| $file_submenu = $mw->Menu(-tearoff => 0, -menuitems => [
8| [command => "~Open",
9| -command =>
10| sub {
11| $file_submenu->entryconfigure('Close', -state => 'normal')
12| }],
13| [command => "~Close",
14| -state => 'disabled'],
15| "-",
16| [command => "E~xit",
17| -command => sub { exit }],
18| ]);
19| $file_m->configure(-menu => $file_submenu);
20| $opt_submenu = $mw->Menu(-tearoff => 0, -menuitems => [
21| [checkbutton => "Sound",
22| -variable => $opt_s],
23| [checkbutton => "Timer",
24| -variable => $opt_t],
25| ]);
26| $opt_m->configure(-menu => $opt_submenu);
27| $mw->configure(-menu => $menu);
28| MainLoop;
Listing 3. menu





Baris 4 menciptakan widget Menu dan disimpan dalam variabel $menu. Baris 5 sampai 26 mengkonfigurasi widget tersebut, dan baris 27 "memasang" $menu pada $mw.

Menu yang dibuat adalah seperti pada gambar 4.

Gambar 4. Menu

Sebuah menu berisi sejumlah entri, dan ada beberapa macam entri menu, yaitu cascade, command, checkbutton, radiobutton, separator, dan tear-off. Pada entri cascade dapat diasosiasikan widget menu yang lain untuk dijadikan submenu. Dalam contoh di atas, baris 5 dan 6 berturut-turut membuat entri cascade $file_m dan $opt_m. Pada baris 19, entri $file_m diasosiasikan dengan menu lain yaitu $file_submenu yang dibuat pada baris 7 sampai 18. Entri-entri yang menyusun $file_submenu ini dibuat melalui opsi -menuitems, sedangkan entri tear-off dihilangkan dengan opsi -tearoff => 0. Widget $file_submenu ini nampak seperti pada gambar 5.

Gambar 5. Submenu File






Pada baris 26, entri cascade yang kedua, yaitu $opt_m diasosiasikan dengan $opt_submenu. Widget $opt_submenu ini memiliki sejumlah entri checkbutton yang juga dibuat melalui opsi -menuitems pada baris 20 sampai 25, dan dapat dilihat pada gambar 6.



Gambar 6. Submenu Options





Satu hal yang menyenangkan dengan widget class Menu ini adalah kemudahan membuat event binding, yaitu cukup dengan membubuhkan tilde (~) di depan karakter yang dimaksud. Sebagai contoh, pada baris 5 kita melihat opsi -label => '~File', yang mengakibatkan kombinasi penekanan Alt dan F akan membuka submenu dari entri cascade tersebut.

Informasi lebih lanjut mengenai menu dapat dilihat pada manual Tk::Menu, dan Tk::Menubutton.

Event Binding

Sebagian widgetclass telah menyediakan cara yang mudah untuk membuat event binding, seperti opsi -command pada widget class Button dan Menu, dan pemakaian karakter tilde pada Menu. Namun seringkali kita perlu mendefinisikan sendiri event binding yang kita inginkan. Untuk ini kita dapat menggunakan methodbind():

$widget->bind(event sequence, callback);

Callback adalah reference ke subrutin yang adalah event handler bagi event X Window yang bersesuaian. Widget yang memanggil fungsi callback tersebut selalu dilewatkan sebagai argumen pertama fungsi tersebut. Dengan memanggil method XEvent() pada argumen pertama ini, kita mendapatkan objek XEvent yang berguna untuk mengetahui informasi berkaitan dengan event yang sedang diterima.

Event sequence adalah string yang mendefinisikan event X Window yang diharapkan, dan format penulisannya adalah sebagai berikut: event-detail>, di mana event utama (yang dicetak tebal) harus ada, sedangkan lainnya opsional. Macam-macam event utama misalkan: Button (ada penekanan tombol mouse), ButtonRelease (ada tombol mouse yang dilepas), Motion (mouse sedang digerakkan), Enter, Key (tombol keyboard ditekan), KeyRelease (tombol keyboard dilepas).

Modifier digunakan jika ada event lain yang menyertai event utama. Misalkan jika tombol o ditekan sementara Alt juga ditekan, maka event sequence-nya menjadi , atau pada klik ganda tombol kiri mouse, event sequence-nya adalah

. Modifier-modifier lainnya misalkan: Shift, Control, Lock.

Detail digunakan jika binding dilakukan pada event yang lebih spesifik lagi. Sebagai contoh, jika mau melakukan binding pada penekanan tombol kiri mouse (bukan sembarang tombol mouse), maka event sequence-nya menjadi: .

Dalam listing 4 diberikan contoh event binding pada penekanan sembarang tombol keyboard dan mouse. Anda dapat mencoba mengubah event sequence pada baris 15 menjadi untuk melihat efek dari penggunaan detail.

1| #!/usr/bin/perl

2| use Tk;

3| $mw = MainWindow->new(-title => "Contoh Event Binding");
4| $mw->geometry("200x200");

5| $mw->bind('' => sub {
6| my $c = shift;
7| my $e = $c->XEvent;
8| print "Tombol keyboard ditekan: ";
9| print " x = ".$e->x." ";
10| print " y = ".$e->y." ";
11| print " keysim = ".$e->K." ";
12| print " ASCII = ".$e->k." ";
13| print " Alphanum = ".$e->A." ";
14| });

15| $mw->bind('



Artikel ini datang dari InfoLINUX
http://www.infolinux.web.id/site

URL cerita ini adalah:
http://www.infolinux.web.id/site/sections.php?artid=42