Geçen hafta boyunca, Java dili ile Applet' lerin
nasıl tasarlandığını incelemeye çalıştım. Mimari kısmında yer alan hemen herşeyi
incelemiştim. Bir AWT bileşenin bir Applet' e nasıl ekleneceğini, bu bileşenin
bir takım temel özelliklerinin nasıl ayarlanacağını, bu bileşene bağlı olay
dinleyicilerinin ne şekilde uygulanması gerektiğini vs... Ancak karşılaştığım en
uğraştırıcı sorun, bileşenlerin bir Applet üzerinde yerleşimlerinin Layout' lar
vasıtasıyla ayarlanmaya çalışmasıydı. Açıkçası, VS.NET gibi bir geliştirme
ortamının sunduğu görsel tasarım rahatlığını özlemiştim. Bu düşünceler
içerisinde Kadıköy' ün arka sokaklarında yürürken çok sevgili bir dostum ile
karşılaştım. Kendisinin sıkı bir Java programcısı olduğunu biliyordum. Beni
ofisine davet etti.
Ofiste bulunduğum süre zarfında konuştuğumuz ve
tartıştığımız tek konu Applet' lerin ve diğer görsel java uygulamalarının kolay
bir şekilde tasarlandığı ve daha çok uygulamanın nasıl çalışacağı ve kodlamaları
ile ilgilenilebildiği, bir başka deyişle asıl önemli olan konulara zaman
ayrılabildiği, vs.net tarzı bir geliştirme ortamının var olup olmadığıydı.
Değerli arkadaşım yüzünde kurnaz bir tebessüm ile, "Sana göstermek istediğim bir
program var" dedi. Bilgisayarın başına geçtik ve ta taaa... JBuilder Enterprise 9!
Adını ve methini çok duyduğum bu yazılım geliştirme ortamını daha önce hiç
denememiştim. Arkadaşım, "Ben java ile geliştirdiğim uygulamaları burada
yazıyorum." dedi. Gözlerimde bir anda bir ışıltı parladığını hissettim. Tek
söylediğim "Yeni makalemi bugün burada yazabilir miyim?" olmuştu.
Her yazılımcı, geliştireceği bir uygulama için
öncelikle, istekleri ve talepleri değerlendirerek işe başlar. Sonra sistemin
analizini ve tasarlanmasını gerçekleştirir. Gerekirse UML şemaları yardımıyla
yazılımın tasarı planınıda oluşturur. Sonraki adım ise, kodlamaların
yapılmasıdır. Ancak çoğu zaman ne ben ne de diğer pek çok yazılımcı Notepad gibi
muhteşem bir editor ile bu tarz projeleri geliştirmek istemez. Çünkü bu tarz bir
yöntem izlendiğinde, yazılımın önem arz eden konularına ayrılacak olan zaman,
notepad ile yazılan kodlarda, bileşenlerin ekran üzerine düzgün bir şekilde
yerleştirilmesinin sağlanması, olay dinleyicilerinin ayarlanması gibi gereksiz
yere zaman alıcı konulara harcanır. Eğer bu böyle olmasaydı çoğumuz bu gün C#
ile geliştireceğimiz projeleri Vs.Net gibi bir ortamda yazmazdık. İşte JBuilder'
da Java ile yazılım geliştirmek üzere tasarlanmış bir yazılım geliştirme
aracıydı. Çok şükür ki,
arkadaşımda bu yazılımın olması benim bu ortamı test etmem ve bir Applet' i örnek
olarak geliştirmem için bulunmaz fırsattı. Bir an bile düşünmeden bu fırsatı
değerlendirmem gerektiğine karar verdim.
O gün ilk yaptığım, Help dosyalarından
Tutorial' lara bakmak olmuştu. Hedefim, bir Applet' i gönül rahatlığıyla ve
kolayca geliştirebilmek ve görsel yazılım geliştirme ortamlarının tüm
nimetlerinden faydalanabilmekti. Bu amaçla, bir Applet' in nasıl tasarlandığının
ve programlandığının anlatıldığı Tutorial' ı bir solukta okuyuverdim. Ardından
hemen uygulamaya geçtim. İlk olarak bana bir proje lazımdı. Vs.Net' teki Solution kavramının karşılığı JBuilder için Project' di.
File-> New
Project sekmesini seçtiğimde, yeni bir proje oluşturmam için gerekli adımları
sağlayan bir sihirbaz ile karşılatım.

Bu ilk adımda tek yaptığım, Proje için bir isim
belirlemek oldu. Hemen ikinci adıma geçtim. İkinci adımda en önemli kısımlardan
birisi, JDK isimli yerdi. Burada geliştireceğim uygulamayı Java' nın hangi
geliştirme kiti ile yazacağımı belirtebilmekteydim. Output Path ile java dosyalarının
derlenmesi sonucu oluşturulacak sınıf dosyalarının hangi yolda olacağı, Backup
Path ile yedeklemelerin nereye yapılacağı belirleniyordu. Working Directory' yi
henüz tam olarak kestirememiştim. Bunun yerine projeyi tamamladığımda bu klasörü
inceleyip ne olup bittiğine bakmaya karar verdim.

Bu adımıda geçtikten sonra sıra proje
oluşturmanın son adımına
gelmişti. Bu adımda, proje hakkında bir takım bilgileri girdim. Örneğin
projenin adını, kısa bir açıklamasını, versiyon numarasını vs... Tutorial'
dan öğrendiğim kadarı ile, bu adımda belirtilenler html bazlı bir dosyada
toplanıp, proje hakkında bir takım temel bilgileri sağlamaktaydı.

Son olarak Finish diyerek projenin oluşturulmasını
sağladım. Proje oluşturulduğunda, son adımda girdiğim verileri içeren bir html
dökümanınında otomatik olarak yazıldığını gördüm.

Artık projem hazır olduğunda göre, bu projeye bir
Applet ekleyebilirdim. Tek yapmam gereken File->New menüsünden açılacak olan
Object Gallery' de Web sekmesine gelmek ve Applet şablonunu seçmekti.

Bu işlemin ardından Applet ile ilgili bir takım
ayarlamaların yapıldığı başka bir sihirbaz ile karşılaştım.

İlk adımda herşey gayet açık ve netti. Appletin
yer alacağı paketin adı standart olarak, proje ismiydi. Applet için bir sınıf
adı belirtilmişti. Bu sınıf adını şu an için değiştirmedim. Base class ile, bir
appletin türetilmesi gereken Applet sınıfını tanımlamıştım. Özellikle dikkatimi
çeken nokta Generate standart methods seçeneğidi. Varsayılan olarak işaretli
olmayan bu seçeneği işaretledim. Çünkü bu seçenek ile, Applet için gerekli
standart bir takım metodların (init gibi) otomatik olarak oluşturulacağını
düşünüyordum. Sihirbazda bir sonraki adım Applet' in dışarıdan parametre alıp
alamayacağı ile ilgiliydi. Şu an için Applet' in html sayfasından parametre
almayacağını düşündüğüm için bu adımı geçerek üçüncü adıma geldim. Üçüncü adımda,
Applet'in test edilmesi için oluşturulacak html dökümanına ait bilgiler yer
alıyordu.

Burada, HTML dökümanın başlık bilgisini, dosya
adını, Applet' in boyutlarını belirledim. Codebase özelliği ile, Applet' in
çalışması için gerekli sınıf dosyalarının bulunduğu klasörler belirleniyordu.
Sonraki adımıda değiştirmeden geçtiğimde, JBuilder benim için, Applet dosyasını
otomatik olarak oluşturmuş ve gerekli kodları yerleştirmişti. Şu haliyle
Applet' in kodları aşağıdaki gibiydi.
package appletuygulamalari;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Applet1 extends Applet
{
private boolean isStandalone = false;
public String getParameter(String key, String def)
{
return isStandalone ?
System.getProperty(key, def):(getParameter(key) != null ?
getParameter(key) : def);
}
public Applet1()
{
}
public void init()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
}
public void start()
{
}
public void stop()
{
}
public void destroy()
{
}
public String getAppletInfo()
{
return "Applet Information";
}
public String[][] getParameterInfo()
{
return null;
}
} |
Oluşturulan bu Applet dosyası ile, geçen haftalarda
oluşturduğum Applet' ler arasında çok fazla fark yoktu. Herşeyden önce, dosyaya baktığımda en azından bir Applet olduğunu, bu
nedenle Applet sınıfından türetildiğini biliyordum. Bununla birlikte, olay
dinleyicilerinin kullanılabilmesi için ve AWT bileşenlerinin oluşturulabilmesi
için gerekli applet, awt ve event paketlerinin referans edildiğinide anlamıştım.
Bir Applet' in yaşam süresi içinde devreye giren init, start, stop , destroy
gibi metodlarında ne işe yaradığını biliyordum. Ekstradan JBuilder tarafından
eklenmiş ilave kodlar vardı. Ancak şu an için bu kodlar pek umurumda değildi.
Bir an önce awt bileşenlerini eklemek istiyordum. Bu amaçla hemen design
sekmesine geçtim ve işte... Oluşturduğum applet ekranı üst taraftaki koca bir
bileşen paleti ile karşımda duruyordu. Sağ tarafta ne olduklarını adım gibi
bildiğim özellikler pencereside yüzüme ayrı bir gülümseme katmıştı.

İlk olarak, appletim ile ilgili bir takım
özellikleri değiştirdim. Sonuç olarak bu değişikliklerin koda nasıl
yansıtılacağını merak ediyordum. Applet' in arka plan rengini değiştirdim. Tam
bu sırada dikkatimi layout isimli özellik çekti. Bu özelliğin aldığı bir takım
değerler vardı.

Layout' ların, AWT bileşenlerinin Applet üzerine
nasıl konumlandırılacağını belirlemekte kullanıldığını biliyordum. Hatta geçen
haftaki denemelerimde en çok zorlandığım yerleşim sorununu bir Layout nesnesi
yardımıyla çözmüştüm. Yinede istediğim gibi olmamıştı. JBuilder, bana bir sürü
layout çeşidi sunmaktaydı. Biraz deneme yanılmadan sonra en uygun olananın
XYLayout olduğunu tespit ettim. Çünkü XYLayout sayesinde, AWT
bileşenlerini Applet üzerinde serbest olarak istediğim yere
konumlandırabilecektim. Yaptığım bu ayarlamalardan sonra kodlarıma baktığımda
aşağıdaki değişikliklerin olduğunu farkettim.
Herşeyden önce,
| XYLayout xYLayout1 = new XYLayout(); |
kod satırları ile XYLayout nesnesi oluşturulmuştu.
Ancak bu Layout nesnesi, java geliştirme kiti ile gelen sınıflardan değildi.
Onun yerine, com.borland.jbcl.layout paketinde yer alan Layout sınıflarından
birisiydi. Zaten bu nedenle, bu paket Applet' in başında uygulamaya import
edilmişti. Diğer yandan jbInit metodu içinde, bu XYLayout' un Applet' e
uygulanması için aşağıdaki kod satırının eklenmiş olduğunu gördüm.
| this.setLayout(xYLayout1); |
Artık Applet' im içim seçtiğim Layout desenide
ayarlandığına göre gönül rahatlığıyla, AWT bileşenlerini oluşturabilirdim. Tek
yapmam gereken bileşen paletinden AWT sekmesine gelmek bir bileşen çizmek ve bu
bileşeni mouse ile Applet' in çalışma alanı üzerine çizmekti.

Bbir kaç basit bileşeni Applet üzerine
yerleştirdikten ve bunların belli başlı özelliklerini Properties penceresinden
değiştirdikten sonra ise bu özelliklerin Applet dosyasına nasıl yansıtıldığını
incelemeye başladım.

Applet üzerinde iki Label bileşeni bir TextField
bileşeni ve bir de Button bileşeni vardı. Bu bileşenlerin bazı özelliklerini
değiştirdiğimde kodun içerisinde JBuilder' ın aşağıdaki eklemeleri yaptığını
farkettim. İlk olarak Applet kodlarının başında, her bir AWT bileşeni için birer
nesne örneği oluşturulduğunu gördüm.
TextField tfSayi = new TextField();
Label label1 = new Label();
Button btnKare = new Button();
Label label2 = new Label(); |
Bu nesnelerin ayarladığım özellikleri ise, jbInit
isimli metod içerisine yazılmıştı. Herhangibir bileşenin özelliklerini ayarlamak
için Properties penceresini kullanmıştım. Tek satır kod yazmadan, JBuilder, bu
işlemlerimi jbInit isimli metodu içerisine otomatik olarak yazıvermişti.
private void jbInit() throws Exception
{
tfSayi.setFont(new java.awt.Font("Dialog", 0, 14));
this.setBackground(new Color(255, 173, 69));
this.setLayout(xYLayout1);
label1.setFont(new java.awt.Font("Dialog", 1, 14));
label1.setText("Sayi");
btnKare.setFont(new java.awt.Font("Dialog", 0, 14));
btnKare.setLabel("Karesi");
label2.setFont(new java.awt.Font("Dialog", 1, 24));
label2.setForeground(Color.red);
label2.setText("label2");
this.add(tfSayi, new XYConstraints(128, 36, 160, 24));
this.add(btnKare, new XYConstraints(295, 34, 90, 30));
this.add(label1, new XYConstraints(69, 36, 46, 26));
this.add(label2, new XYConstraints(125, 74, 262, 37));
} |
TextField bileşeninin Font ayarlamaları setFont
metodu ile yapılmıştı. Aynı metod diğer bileşenlerde de kullanılmıştı. Applet'
in arka plan rengi setBackground metodu kullanılarak belirlenmekteydi. Bu metoda
parametre olarak Color sınıfından bir nesne aktarılmış ve bu nesde R,G,B
(Red,Green,Blue) renk tonlarını esas alarak arka planı renklendirmişti.
Bileşenlerin başlıklarında yazacak metinler setText veya setLabel metodları ile
belirlenmekteydi.
Bu metod içerisinde belkide en önemli kısım,
bileşenlerin Applet' e add metodu ile ekleniş şekilleriyle ilgiliydi. Bu metod
iki parametre almıştı. İlk parametre ile, hangi bileşenin ekleneceği
belirleniyordu. İkinci parametre ise XYConstraints sınıfından bir nesne
almaktaydı. Bu nesnenin 4 parametresinden ilk ikisi bileşenin boyutlarını son
ikisi ise X ve Y koordinatlarını belirtmekteydi. XYConstraints sınıfıda,
XYLayout sınıfı gibi, com.borland.jbcl.layout paketinde yer alan bir sınıftı.
Elbette add metodunun bu şeklinin uygulanması, bir XYLayout nesnesinin bu Applet
için uygulanmasınıda gerektirmekteydi.
jbInit metodu, bileşenlerin özelliklerinin
belirlenmesi ve Applet' e eklenmesinde görev alıyordu. Normalde Notepad ile
yazılan bir Applet' te bu kod satırlarını init metodu içerisine doğrudan
yerleştirecektim. Nitekim JBuilder bu işi daha güvenli bir hale getirmek ve
bileşenlerin Applet' e eklenmesi sırasında oluşabilecek istisnaları kontrol
altına alabilmek için init metodunu aşağıdaki gibi düzenlemişti.
public void init()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
} |
Sırada ise Button bileşenine basıldığında
gerçekleştirilecek olayların kodlanması vardı. Bu amaçla ilk yaptığım, Button
bileşenine çift tıklamak oldu. Olay metodlarının bu şekilde eklendiklerinde, o
bileşen için varsayılan olay metodunun oluşturulacağını biliyordum. Olay metodu
eklemesi için elbetteki Events sekmesinide kullanabilirdim. Örneğin, Button
bileşeni ile kullanabileceğim olay metodları aşağıdaki şekilde görülenlerdi.

Sonuç olarak, JBuilder aşağıdaki gibi bir olay
metodu oluşturdu.
void
btnKare_actionPerformed(ActionEvent e)
{
} |
Normal şartlarda, bir Button bileşeni için olay
metodu oluşturmak isteseydim, aşağıdaki gibi bir metod yazmam gerekicekti. Bu
metod içinde, Applet içinde actionPerformed olayına cevap verebilecek bir kaç
bileşen olacağını düşünerekten, hangi bileşen için bu olay metodunun
çalıştırılacağına ve ne şekilde çalışacağına karar vermek amacıyla, ActionEvent
parametresinin getSource metodunnu kullanmam gerekiyordu. Oysaki JBuilder bunu
yapmamıştı. Onun yerine sanki sadece bu Button bileşeni için çalışacak bir olay
metodu yazmıştı.
public void
actionPerformed(ActionEvent e)
{
if(e.getSource()==btnYaz)
{
}
} |
Peki JBuilder bu durumu nasıl gerçekleştirmişti?
Kodları incelemeye devam ettim. actionPerformed olay metodu için, ActionListener
arayüzünün Applet sınıfına uygulanmış olması gerekiyordu. Oysaki Applet' e ait
sınıf tanımlamasında böyle bir arayüz uygulanmamıştı.
| public class Applet1 extends Applet { |
Tam bu sırada Applet'e ikinci bir sınıfın daha
eklendiğini gördüm.
class Applet1_btnKare_actionAdapter
implements java.awt.event.ActionListener
{
Applet1 adaptee;
Applet1_btnKare_actionAdapter(Applet1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.btnKare_actionPerformed(e);
}
} |
Asıl bu sınıf ActionListener arayüzün uygulamıştı.
Sınıfın adı, Applet ve Bileşen adlarından oluşturulmuştu. Sınıf içinde ilk
satırda, Applet1 sınıfından (ki bu appletimin adı oluyordu) bir nesne tanımlanmıştı.
Sınıfın yapıcı metodunda da bu Applet1 nesnesi kullanılmıştı. Peki ama bunlar ne
anlama geliyordu. Sorunun cevabı izleyen actionPerformed metodunda yatmaktaydı.
Button bileşenine basıldığında, Applet' in olay dinleyicisi bu yeni sınıf
içerisinde yer alan actionPerformed metodunu devreye sokuyordu. Bu metod ise,
ActionEvent parametresini, button bileşeni için oluşturulan
btnKare_actionPerformed metoduna göndermekteydi.
Bu tasarım deseni sayesinde, her bileşen için
yazılacak olay metodları ayrı ayrı olacak şekilde oluşturulmaktaydı. Böylece
bileşen olaylarının tek bir metod içinden ayrıştırılarak ele alınmasının önüne
geçilmiş oluyordu. Ancak yinede eksik bir şeyler vardı. Sonuç olarak bir
şekilde, olay dinleyicisinin bir yerlerde bu Button bileşeni için eklenmiş
olması gerekirdi. Kodu bir kere daha inceledikten sonra, JbInit metodunda
aşağıdaki satırı farkettim.
| btnKare.addActionListener(new
Applet1_btnKare_actionAdapter(this)); |
Normalde, bu Button bileşeni için olay dinleyicisi
eklenirken addActionListener metodu sadece this parametresini alırdı. Burada
ise, olay dinleyicisi olarak, Applet1_btnKare_actionAdapter sınıfı türünden bir
nesne oluşturulmuş ve bu nesneye this parametresi yani Applet sınıfının kendisi
gönderilmişti. Bir başka deyişle olay dinleme görevini bu yeni sınıf
üstlenmekteydi.
Artık Button bileşenine basıldığında neler olacağını
kodlayabilirdim. Burada çok daha güzel bir şey farkettim. Borland uzun süredir,
geliştirme ortamlarında intellisense özelliğini kullanıyordu. Bu özelliğin
JBuilder içindede olması gerçekten çok iyiydi. Nitekim . işaretinden sonra
ilgili nesne ile kullanabileceğim metodlar aşağıdaki gibi karşıma geliyordu. Tek
gördüğüm eksik, bir metod adı üstüne geldiğimde, Vs.Net' te olduğu gibi metod
hakkında kısa bir açıklamanın ekrana gelmiyor olmasıydı.

Buna rağmen kodları yazmak kolaydı. Bu mutluluk ve huzur içinde aşağıdaki kodları oluşturdum.
Kodlarda gerçekleşen olay son derece basitti. Güvenli bir try-catch bloğu
içinde, önce TextField' a girilen değeri getText metodu ile almıştım. Ardından,
bu değeri double tipinden bir değişkene aktarmak için Double sınıfının
parseDouble metodunu kullandım. Sonra Math sınıfının pow metodu ile bu değerin
karesini buldum ve sonucu String sınıfının valueOf metodu ile String türünden
bir değişkene aktardım. Son olarak bu değeri label bileşeninde setText metodu
ile gösterdim.
void
btnKare_actionPerformed(ActionEvent e)
{
try
{
String sayi = tfSayi.getText();
double
deger=Double.parseDouble(sayi);
deger=java.lang.Math.pow(deger,2);
String sonuc=String.valueOf(deger);
label2.setText(sonuc);
}
catch(Exception hata)
{
label2.setText(hata.toString());
}
} |
Tüm bu işlemlerden sonra tek yapmam gereken,
projeyi derlemek ve çalıştırmaktı.

Sonuç ise aşağıdaki gibi oldu. Applet başarılı bir
şekilde çalıştı. Bu mutluluğu yaşarken güneşin çoktan battığını ve ofisin
kapanmak üzere olduğunu farkettim. Masamda 3 kulplu bardak içi boş ve hoş bir
kahve kokusu ile duruyordu. Java dili ile birşeyler geliştirmenin bu kadar
eğlenceli ve güzel olacağını tahmin etmemiştim. Ancak elbetteki dilin
temellerini bilmeden yaptıklarımdanda bir şey anlayamaz ve beceremezdim. Artık
rahat ve huzurlu bir şekilde evime dönebilirdim.

Burak Selim ŞENYURT
selim@bsenyurt.com