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
jigsawpuzzle 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.
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
handlerevent tersebut. Langkah ini disebut dengan
event
binding. Baris 6 melakukan eventbinding 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 eventloop 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.
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 widgetclass 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
widgetclass 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.