Geçen hafta boyunca Applet' lerin büyülü dünyasını
daha çok keşfedebilmek için uğraştım durdum. Nitekim Applet' leri daha etkin bir
şekilde kullanabileceğimi ve Applet'lerin çok daha fazlasını sunduğunu
biliyordum. Örneğin, kullanıcılar ile dinamik etkileşime geçilmesini sağlayacak
tarzda applet' ler üzerinde çalışabilirdim. Bu konuda aklıma ilk gelen, bilgi
giriş formu ekranı oldu. İlk başta nereden başlamam gerektiğini bilmiyordum.
Applet' lerin çalışma mimarisinden haberim vardı. Ancak, görsel öğeleri bu
applet' ler üzerinde nasıl oluşturabilirdim? Dahada önemlisi, bu görsel
nesnelerin, kullanıcı aktivitelerine cevap vermesini nasıl programlayabilirdim?
Bir başka deyişle, görsel programlamanın en önemli yapıtaşlarından birisi olan
olay-güdümlü programlamayı nasıl gerçekleştirebilirdim? Tüm bu soruların
cevaplarını bulmak maksadıyla, hafta boyunca araştırmalarımı sürdürdüm.
Kilit nokta, Java dilinin Awt isimli (Abstract
Windows Toolkit) paketiydi. Awt hem applet' ler için hemde ileride incelemeyi
düşündüğüm normal GUI (Graphical User Interface) ler için ortak nesne
modellerini kapsülleyen bir paketti. İlk okuduğumda bu paketin, Voltran' ın
parçalarından birisi olduğunu zannetmiştim. Ancak sağladığı imkanlar ile,
Voltran' ın değil gövdesi tüm benliğini oluşturabilirdim. İşin geyiği bir yana,
Awt paketi, java ile geliştirilen herhangibir GUI uygulaması için gerekli olan
tüm görsel bileşenleri sağlamaktaydı. Hatta bu bileşenlerin her GUI
uygulamasında aynı tipte görünmesinede imkan tanıyordu.
Özellikle Visual Studio.Net gibi görsel geliştirme
ortamlarında program arayüzlerini (interface programlama değil, görsel tasarım
anlamında) tasarlamak son derece kolay. Ama ister .net platformunda olsun ister
Java platformunda, nesne yönelimli dillerin doğası gereği tüm görsel
bileşenlerde aslında birer sınıf modelinin örneklemelerinden başka bir şey
değiller. Dolayısıyla Awt paketi içindeki görsel bileşenlerinde birer sınıf
modeli olduğunu belirtmekte yarar var. Örneğin, sayfalarda gösterebileceğim
butonlar Button sınıfına ait nesne örnekleri olacak. Sadece metin bilgisi
taşıyan okuma amaçlı Label bileşenleri, Label sınıfına ait olacak. Yada
Checkbox, TextField, TextArea, List, Image kontrolleri vs...
Artık bir noktadan başlamam gerektiğini
düşünüyordum. Kahvemden bir yudum aldım ve ilk önce nasıl bir form tasarlamak
istediğime karar verdim. Bunu kağıt üzerinde çizmek kolaydı ancak dijital ortama
aktarmak zordu. Tasviri tam yapmak için, Vs.Net editörünü kullandım ve aşağıdaki
gibi bir formu, applet olarak tasarlamaya karar verdim.

Bu formu oluşturmak için hangi sınıfları kullanmam
gerektiğinede, JSDK'dan baktım. Şu ana kadar her şey açık ve netti. Şimdi sıra
kodlama kısmına gelmişti. Aslında ne yapmam gerektiğini açıkça tahmin
edebiliyordum. Applet, bileşenleri üzerinde barındıracak yer olduğuna göre,
Applet' i oluştururken, başka bir deyişle applet' i çalışır hale getitirken bu
nesneleri yükleyebilirdim. Ancak bundan önce bu bileşen nesnelerini oluşturmam
ve daha sonra bir şekilde Applet'e eklemem gerekiyordu. Felsefe işte bu kadar
basitti. Felsefenin asıl karışacağı noktanın, bu bileşen nesnelerinin olaylara
cevap verebilecek şekilde kodlanmasında oluşacağını da hissediyordum. Ancak ilk
etapta, öncelikle appleti tasarlamam ve en azından bileşenleri applet üzerinde
sorunsuz bir şekilde göstermem gerektiği kanısındaydım. Hemen kolları sıvadım ve
aşağıdaki applet sınıfını oluşturdum.
import java.awt.*;
import java.applet.Applet;
public class Gui_1 extends Applet
{
public void init()
{
setBackground(Color.white);
Label lbAd=new Label("Ad ");
Label lbSoyad=new Label("Soyad ");
Label lbAdres=new Label("Adres ");
Label lbCinsiyet=new Label("Cinsiyet
");
Label lbHobi=new Label("Hobi ");
TextField txtAd=new TextField();
TextField txtSoyad=new TextField();
TextArea txtAdres=new TextArea(2,5);
CheckboxGroup cbCinsiyet=new
CheckboxGroup();
Checkbox cbInternet=new
Checkbox("Internet");
Checkbox cbMuzik=new
Checkbox("Muzik");
Checkbox cbSinema=new
Checkbox("Sinema");
Checkbox cbTiyatro=new
Checkbox("Tiyatro");
Button btnYaz=new Button("Yaz");
add(lbAd);
add(txtAd);
add(lbSoyad);
add(txtSoyad);
add(lbAdres);
add(txtAdres);
add(lbCinsiyet);
add(new
Checkbox("Erkek",cbCinsiyet,true));
add(new
Checkbox("Kadin",cbCinsiyet,false));
add(lbHobi);
add(cbInternet);
add(cbMuzik);
add(cbSinema);
add(cbTiyatro);
add(btnYaz);
}
} |
Bu uzun kod dosyasında temel olarak yapılan
işlemler çok basitti. Herşeyden önce nesneleri oluşturabileceğim en uygun yer
init metoduydu. Burada her bir görsel bileşen nesnesini teker teker new
operatörü ile oluşturdum. Label bileşenleri için yapıcılarına Label'ın başlık
metnini gönderdim. Aynı işlemi, CheckBox bileşenleri ve Button bileşeni içinde
yaptım. Böylece ekrandaki Label, Checkbox ve Button bileşenlerinin başlıklarının
ne olacağınıda otomatik olarak belirlemiş oldum. Textfield bileşenleri içinde
parametreler girilebilir. Özellikle Textfield' ın boyutunu belirlemek için.
Textarea bileşeni için ise, iki parametre girdim. İlki satır sayısını ikinciside
sütun sayısının göstermekte. Burada tek özel oluşum radyo buton dediğim
CheckboxGroup bileşenine ait. Bu bileşene, yine Checkbox bileşenleri ekleniyor.
Yani bir CheckboxGroup bileşeni birden fazla Checkbox kontorlünü aynı isim
altında gruplamak ve böylece bu bileşenlerden sadece birisinin seçili olmasını
garanti etmek amacıyla kullanılmakta.
Bu bileşen örneklerinin oluşturulmasından sonra
tek yaptığım add metodunu kullanarak bunları Applet' imin üzerine eklemek oldu.
Sonuç mu? Aslında göstermeye çekiniyorum. Çünkü hiçte umduğum gibi değil. Java
bytecode dosyasının class olarak derledikten sonra bir html sayfasına <Applet
tagını kullanarak ekledim. İşte sonuç;

Ahhhh!!! Ahhh. Nerede güzelim Visual Studio.Net,
Dreamweaver, Frontpage....İyi güzel bileşenleri oluşturmuştum, applet' ede
başarılı bir şekilde eklemiştim. Ama ya görsel tasarımın zerafeti ne olacak. Tam
bu noktada işte çakılıp kalmıştım. Kaynaklarıma baktım benim yaptığım bu estetik
abidesini onlarda başarmışlardı. Kaynaklarımı biraz daha araştırdıktan sonra
aslında bu tasarım ve sayfaya yerleştirme işinin bazı kitaplarda bölüm olarak
işlendiğini gördüm. Ancak şu an için bana en azından ızgaralanmış bir görümü
hazırlayabileceğim bir teknik gerekiyordu. Sonunda buldum ama... Gerçi bulana
kadar bir kaç fincan kahveyide bitirdim. İşin sırrı Olinde değil, tabiki
sağdakindeydi. Yani Layout tekniği. Uyguladığım teknik GridLayout tekniği. Tek
yapmam gereken tüm kontrolleri eklemeden önce, Applet üzerinde bir GridLayout
yani ızgara belirlemekti. Bunu gerçekleştirmek için Applet'in init metodunun en
başına aşağıdaki kod satırını ekledim.
| setLayout(new GridLayout(15,2)); |
Bu satır ile Applet'in web sayfasında kaplayacağı
alanı, 15 satır ve 2 sütuna bölmüştüm. Artık GUI bileşenleri sırasıyla
yerleşecekti. Ancak yinede sonuç istediğim gibi olmamıştı.

Hiç yoktan iyidir diyerek devam etmek zorundaydım.
Ancak Layout ayarlamaları ile ilgili olarak başka bir kahve molasında daha derin
bir araştırma yapmayıda kafama koymuştum. Olay yerinden uzaklaşırken, en azından
applet üzerinde dinamik olarak görsel bileşenlerin nasıl eklendiğini anlamış ve
bir kaç bileşenide öğrenmiştim. Asıl merak ettiğim, butona basıldığında olmasını
istediklerimi nasıl yazacağımdı? Bunun için, C# dilinde özellikle görsel
programlamada delegeler ile yakın ilişkide olan event'lar kullanılıyordu. Java
dilindede durum çok farklı değildi ancak anlaşılması daha kolaydı. Java
dilindede, kullanıcı tepkilerini ele alabilmek için delegasyon mantığı
kullanılıyordu. Bu modelin en önemli yanı, görsel bileşenlerinin kullanıcı
tepkilerini algılayabilmelerini istediğimiz Applet sınıfına, ActionListener
arayüzünü uygulamamız gerekliliğiydi. Kolları sıvadım ve ilk olarak, en basit
haliyle, Button bileşenime tıklandığında meydana gelecek kodları hazırladım.
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Gui_1 extends Applet implements ActionListener
{
TextField txtAd;
TextField txtSoyad;
Button btnYaz;
public void init()
{
setBackground(Color.white);
Label lbAd=new Label("Ad ");
Label lbSoyad=new Label("Soyad ");
Label lbAdres=new Label("Adres ");
Label lbCinsiyet=new Label("Cinsiyet
");
Label lbHobi=new Label("Hobi ");
txtAd=new TextField();
txtSoyad=new TextField();
TextArea txtAdres=new TextArea(2,5);
CheckboxGroup cbCinsiyet=new
CheckboxGroup();
Checkbox cbInternet=new
Checkbox("Internet");
Checkbox cbMuzik=new
Checkbox("Muzik");
Checkbox cbSinema=new
Checkbox("Sinema");
Checkbox cbTiyatro=new
Checkbox("Tiyatro");
btnYaz=new Button("Yaz");
setLayout(new GridLayout(15,2));
add(lbAd);
add(txtAd);
add(lbSoyad);
add(txtSoyad);
add(lbAdres);
add(txtAdres);
add(lbCinsiyet);
add(new
Checkbox("Erkek",cbCinsiyet,true));
add(new
Checkbox("Kadin",cbCinsiyet,false));
add(lbHobi);
add(cbInternet);
add(cbMuzik);
add(cbSinema);
add(cbTiyatro);
add(btnYaz);
btnYaz.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==btnYaz)
{
System.out.println(txtAd.getText()+" "+txtSoyad.getText());
}
}
} |
Burada kullanılan tekniği anlamanın çok önemli
olduğunu düşünüyorum. Öncelikle Applet'in üzerindeki nesnelerin olaylarını
dinleyecek şekilde programlamalıydım. Bunu gerçekleştirebilmek için, sınıfa
ActionListener arayüzünü uyguladım. Ardından hangi bileşen için bir olay
dinlemesinin gerçekleştirilmesini istiyorsam, o nesne içi addActionListener
metodunu this parametresi ile kullandım. Böylece, bu örnekteki Button bileşenine
bu applet içinde yapılacak tıklamalar ele alınabilecek ve kodlanabilecekti.
Başka bir deyişle, nesneye ait olası olayların dinlemeye alınmasını sağlamıştım.
Bu işlemin ardından elbetteki, olay meydana geldiğinde çalıştırılacak kodları
yazacağım bir metod gerekliydi. İşte buda, Button bileşenlerine yapılan
tıklamaları dinleyen actionPerformed metodu. Bu metod ActionEvent isimli bir
parametre alıyor. Bu parametre sayesinde, hangi buton bileşenine tıklandığını
dinleyebilirim. İşte böylece buton bileşenine basıldığında işleyecek olan
satırları burada yazmış oldum. Şimdi bu sistemi deneme vakti geldi.
Tarayıcıda sayfamı çalıştırdım txtAd ve txtSoyad
kontrollerine isim ve soyisim bilgilerimi girdim buton' a tıkladım ve ekranın
sağ alt köşesindeki System Tray'da yer alan JVM kahve sembölünden, Open Console
diyerek, console penceresine geçtim. Sonuç olarak tıklama olayım algılanmış ve
olaya karşılık gelen kod satırları çalıştırılmıştı.

Şimdi aklıma takılan başka bir nokta vardı. Eğer
applet'imde iki button bileşeni olsaydı. Her biri için ayrı ayrı olay
dinleyicilerimi yazacaktım? Nitekim, actionPerformed metodunun yapısı buna
müsait değildi. Bu amaçla, applet' e TextField ve TextArea kontrollerinin
içeriğini temizleyecek yeni bir Button bileşeni ekledim. Kodun son hali
aşağıdaki gibi oldu.
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Gui_1 extends Applet implements ActionListener
{
TextField txtAd;
TextField txtSoyad;
TextArea txtAdres;
Button btnYaz;
Button btnSil;
public void init()
{
setBackground(Color.white);
Label lbAd=new Label("Ad ");
Label lbSoyad=new Label("Soyad ");
Label lbAdres=new Label("Adres ");
Label lbCinsiyet=new Label("Cinsiyet
");
Label lbHobi=new Label("Hobi ");
txtAd=new TextField();
txtSoyad=new TextField();
txtAdres=new TextArea(2,5);
CheckboxGroup cbCinsiyet=new
CheckboxGroup();
Checkbox cbInternet=new
Checkbox("Internet");
Checkbox cbMuzik=new
Checkbox("Muzik");
Checkbox cbSinema=new
Checkbox("Sinema");
Checkbox cbTiyatro=new
Checkbox("Tiyatro");
btnYaz=new Button("Yaz");
btnSil=new Button("Sil");
setLayout(new GridLayout(16,2));
add(lbAd);
add(txtAd);
add(lbSoyad);
add(txtSoyad);
add(lbAdres);
add(txtAdres);
add(lbCinsiyet);
add(new
Checkbox("Erkek",cbCinsiyet,true));
add(new
Checkbox("Kadin",cbCinsiyet,false));
add(lbHobi);
add(cbInternet);
add(cbMuzik);
add(cbSinema);
add(cbTiyatro);
add(btnYaz);
add(btnSil);
btnYaz.addActionListener(this);
btnSil.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==btnYaz)
{
System.out.println(txtAd.getText()+" "+txtSoyad.getText());
}
else if(e.getSource()==btnSil)
{
txtAd.setText("");
txtSoyad.setText("");
txtAdres.setText("");
repaint();
}
}
} |
İlk hali;

Sil başlıklı Button bileşenine tıklandıktan
sonraki hali.

Her iki buton bileşenide, aynı olay dinleyicisi
içerisinde ele alınmıştı. actionPerformed dinleyicisinde, hangi butona
tıklandığı, ActionEvent parametresinin getSource metodu ile tespit edilmekteydi.
Elbetteki awt paketinde yer alan diğer görsel bileşenler için sadece bu olay
dinleyicisi söz konusu değildi. İşin aslı, nesneler üzerindeki kullanıcı
etkilerine göre dinleyiciler tanımlanmıştı. Örneğin, CheckBox bileşenine
tıklanması bu bileşenin durumunun değişmesi anlamına gelmekteydi ki bu durumda,
ItemListener dinleyici metodu bu etkiyi ele alacaktı. Diğer nesneler içinde
benzer durumlar söz konusu. Ama ne zaman? Bir dahaki kahve kokusunda.
Burak Selim ŞENYURT
selim@bsenyurt.com