Geçtiğimiz hafta hayatımın en mutlu günlerinden
birisini, değerli bir arkadaşımının ofisinde, bilgisayarının başında JBuilder
kullanarak geçirdim. Bu hafta, o günü mumla aradığımı söylemek isterim. JBuilder
ile daha önce hiç uygulama geliştirmemiş olmama rağmen, kolayca adapte olmuştum.
Elbetteki benim için en büyük rahatlığı, Applet gibi görsel uygulamaların ekran
tasarımlarının son derece kolay bir şekilde yapılabilmesiydi. Bu hafta yine
sevimsiz notepad editorüm ile başbaşayım. Aslında amacım arkadaşımın
bilgisayarında JBuilder ile başka çalışmalarda yapmaktı. Fakat kendisi tatile
çıktığı için banada notepad ile bir kahve molası geçirmek kaldı.
Özellikle notepad editorünü kullanarak applet
tasarlamanın en zor yanlarından birisi, applet üzerindeki bileşenlerin yerleşim
şekillerinin ayarlanmasının zorluğudur. Bu hafta ne yapıp edip, bu fobiyi
yenmeye karar verdim ve java dilinde Layout kavramını incelemeye başladım.
Layout' lar applet üzerine yerleştirilecek bileşenlerin belli bir nizamda
olmasını sağlamaktadırlar. Java paketiyle gelen Layout sınıfları 5 adettir.
| Java Layouts |
|
GridLayout |
|
BorderLayout |
|
FlowLayout |
|
CardLayout |
|
GridBagLayout |
Öncelikle işe en kolay olanından başladım.
FlowLayout. Layout sınıflarını anlamanın en iyi yolu elbette onları bir örnek
üzerinde uygulamakla mümkün olabilirdi. Bu amaçla çok basit olarak aşağıdaki
gibi bir java örneği geliştirdim.
import java.awt.*;
import java.applet.Applet;
public class Layouts extends Applet
{
TextField tf1;
TextField tf2;
Button bt1;
Label lb1;
Label lb2;
public void init()
{
setLayout(new
FlowLayout(FlowLayout.CENTER,15,30));
lb1=new Label("Username");
tf1=new TextField(25);
lb2=new Label("Password");
tf2=new TextField(25);
bt1=new Button(" OK ");
add(lb1);
add(tf1);
add(lb2);
add(tf2);
add(bt1);
}
} |
Burada tek yaptığım, applet üzerine yerleşecek
bileşenlerin FlowLayout 'a göre düzenlenmesiydi. Applet' in FlowLayout' u
uygulayacağını belirtmek için,
| setLayout(new
FlowLayout(FlowLayout.CENTER,15,30)); |
kod satırını kullandım. Burada, bileşenlerin
Applet üzerinde bulundukları satırda ortalanarak yerleştirilecekleri ve yatay
olarak aralarında 15 piksel, dikey olarak ise 30 piksel boşuk olacağı
belirtiliyor. Peki ama bu yerleşim nasıl oluyor? Nitekim kaynaklarda,
FlowLayout' un bileşenleri sola ve aşağı doğru hizaladığı söyleniyordu.
Denemekten başka çarem olmadığını düşünerek hemen işe koyuldum ve basit bir html
sayfasında applet tagımı aşağıdaki gibi ekledim.
<APPLET CODE="Layouts.class"
width="300" height="500">
</APPLET> |
Şimdi bu html sayfasını çalıştırdığımda aşağıdaki
gibi bir görüntü elde ettim.

Doğruyu söylemek gerekirse kel alaka bir tasarım
olmuştu. FlowLayout için diğer iki durum, yerleşim şeklinin sola dayalı olmasını
belirten FlowLayout.LEFT ve sağa dayalı olmasını belirten FlowLayout.RIGHT
seçenekleriydi. Önce LEFT durumunu inceledim ve aşağıdaki ekran görüntüsünü elde
ettim.

Sanki durumu anlamaya başlamış gibiydim. Bu kez
RIGHT durumunu denedim ve aşağıdaki sonucu elde ettim.
Görünen o ki, düzgün bir tasarım yapmak istiyorsam
bunu öncelikle kafamda yapmalı ve Applet' in boyutlarını çok tutarlı
belirtmeliydim. Ancak bu şekilde düzgün bir tasarım elde edebilirdim. Şu an için
deneme yanılma yöntemini kullanmaktan başka bir şey aklıma gelmiyor açıkçası.
Örneğin, en uzun Label olan Username ile TextField' ların boyu düşünüldüğünde
Applet tagını aşağıdaki gibi düzenlemek daha mantıklı geliyordu.
<APPLET CODE="Layouts.class"
width="250" height="500">
</APPLET> |
Java kodunda da, FlowLayout dizilimini
FlowLayout.LEFT olarak belirlediğimde, daha düzenli bir ekran görüntüsü elde
ettim. Gerçi bu varsayımsal yaklaşım ile kullanılan teknik pek hoşuma gitmemişti
ama en azından buz dağının üst kısmını biraz olsun yontmayı başarabilmiştim.

Bu örnekten sonra, arkadaşımı bir kat daha özledim
desem yalan olmaz. Heleki JBuilder uygulamasını. Oradaki tasarım rahatlığı
gerçektende muhteşemdi. Bu sırada aklıma başka bir şey geldi. Acaba, bir Layout
düzeneğini, bir Panel bileşenine uygulayabilir miydim? Eğer böyle bir şey söz
konusu olursa, görsel tasarımı biraz daha kolaylaştırabilirdim. Bu amaçla
aşağıdaki gibi bir örnek geliştirdim.
import java.awt.*;
import java.applet.Applet;
public class Layouts extends Applet
{
TextField tf1;
TextField tf2;
Button bt1;
Label lb1;
Label lb2;
Panel p1;
public void init()
{
p1=new Panel();
p1.setBackground(Color.yellow);
p1.setLayout(new
FlowLayout(FlowLayout.LEFT));
lb1=new Label("Username");
tf1=new TextField(25);
lb2=new Label("Password");
tf2=new TextField(25);
bt1=new Button(" OK ");
p1.add(lb1);
p1.add(tf1);
p1.add(lb2);
p1.add(tf2);
p1.add(bt1);
add(p1);
}
} |
İlk olarak, bir Panel bileşeni oluşturdum ve bu
bileşen üzerine yerleştireceğim diğer bileşenlerin FlowLayout düzeneğine göre
konumlandırılmalarını sağlamak için Panel bileşenine,
| p1.setLayout(new
FlowLayout(FlowLayout.LEFT)); |
satırındaki setLayout metodunu uyguladım. Böylece,
Panel bileşeni üzerine yerleşecek bileşenler, FlowLayot düzeneğine göre, Layout'
un solundan hizalanacak şekilde konumlanacaklardı. Bileşenleri Panel' e eklemek
için, Panel sınıfına ait add metodunu kullandım. Tabi bu işlemlerden sonra Panel
bileşeninide, Applet' e add metodu ile eklemeyi unutmadım. Bu adımlardan sonra,
Java dosyasını derleyip applet' i içeren html sayfasını ilk çalıştırdığımda
aşağıdaki sonucu elde ettim.

Böyle olacağı belliydi zaten. Applet tagında width
özelliğini arttırmam gerekiyordu. Bu değeri 600 olarak belirledim. Şimdi elde
ettiğim sonuç çok daha iyiydi.

Layout sınıfları bitmek bilmiyordu. Sırada
BorderLayout sınıfı vardı. Bu sınıfın en ilginç yanı, Applet ekranının, NBA
basketbol takımlarının liglerinde gruplanışlarına benzer bir yapıda
ayrıştırılıyor olmasıydı. Doğu Grubu, Merkez Grubu, Batı Grubu, Kuzey Grubu ve
Güney Grubu. Yani, applet üzerine ekleyeceğim bileşenleri, bu gruplara
yerleştirmem gerekiyordu. Bunu görsel olarak anlayabilmek için, kaynaklarımı
araştırdım ve yukarıdaki örneğe bu kez BorderLayout düzeneğini uyguladım.
import java.awt.*;
import java.applet.Applet;
public class Layouts extends Applet
{
TextField tf1;
TextField tf2;
Button bt1;
Label lb1;
Label lb2;
public void init()
{
setLayout(new BorderLayout());
lb1=new Label("Username");
tf1=new TextField(25);
lb2=new Label("Password");
tf2=new TextField(25);
bt1=new Button(" OK ");
add("North",lb1);
add("Center",tf1);
add("West",lb2);
add("South",tf2);
add("East",bt1);
}
} |
Applet üzerindeki bileşenlerin BorderLayout
düzeneğine göre yerleştirileceğini,
| setLayout(new BorderLayout()); |
satırı belirtiyordu. BorderLayout, Applet' i 5 yön
bölgesine böldüğü için, her bileşeni Applet' e eklerken add metoduna ilk
parametre olarak, bileşenin hangi bölgeye yerleştirileceğinin belirtilmesi
gerekiyordu. Bu işlemde aşağıdaki satırla gerçekleştirmekteydi.
add("North",lb1);
add("Center",tf1);
add("West",lb2);
add("South",tf2);
add("East",bt1); |
Örneğin, tf2 isimli TextField bileşeni Applet'in
South (Güney) bölgesine yerleşecekti. Artık Applet' i kullandığım html sayfasını
çalıştırıp sonuçları görmek istiyordum. Ama sonuçları göstermeye çekiniyorum
açıkçası. BorderLayout' un Applet ekranına uygulanması sonucu aşağıdaki gibi
muhteşem ötesi bir tasarım elde ettim. Tarihi bir başarı olduğunu belirtmek
isterim.

İşin kötü yanı, belli bir bölgeye sadece tek bir
bileşen yerleştirebiliyor olmasıydı. BorderLayout düzeneğinin nerede
kullanılacağını düşünürken, diğer Layout' ları incelemenin daha uygun olacağını
farkettim. Nitekim, BorderLayout her ne kadar yukarıdaki ekran tasarımı için
uygun olmasada elbetteki kullanıldığı bir takım yerler olabilirdi. Layout' lar
ile uğraşmak gerçekten insana sıkıcı geliyor. Artık JBuilder gibi görsel tasarım
araçlarının o kadar paraya gerçekten deydiğini söyleyebilirim. Hemde gönül
rahatlığıyla. Bu düşünceler eşliğinde kendime yeni bir fincan kahve aldıktan
sonra bir diğer Layout sınıfı olan GridLayout' u incelemeye başladım. GridLayout
ile nispeten biraz daha güzel ve kolay form tasarımları oluşturabileceğimi
düşünüyordum. Yapmam gereken son derece basitti. Aynı örneği GridLayout sınıfı
ile geliştirmek.
import java.awt.*;
import java.applet.Applet;
public class Layouts extends Applet
{
TextField tf1;
TextField tf2;
Button bt1;
Label lb1;
Label lb2;
Panel p1;
Panel p2;
public void init()
{
setLayout(new GridLayout(2,1));
p1=new Panel();
p1.setBackground(Color.orange);
p1.setLayout(new
FlowLayout(FlowLayout.LEFT));
p2=new Panel();
p2.setBackground(Color.blue);
lb1=new Label("Username");
tf1=new TextField(25);
lb2=new Label("Password");
tf2=new TextField(25);
bt1=new Button(" OK ");
p1.add(lb1);
p1.add(tf1);
p1.add(lb2);
p1.add(tf2);
p1.add(bt1);
add(p1);
add(p2);
}
} |
Bu kez, Applet'e iki Panel bileşeni ekledim. Bu
iki Panel bileşeninde 2 satır ve 1 sütunluk bir GridLayout düzeneği içinde
Applet' e ekledim. GridLayout nesneleri, temel olarak iki parametre almakta. İlk
parametre, satır sayısını belirtirken, ikinci parametrede doğal olarak sütun
sayısını belirtiyor. Bununla birlikte, GridLayout sınıfının 4 parametre alan bir
diğer yapıcısıda mevcut. Bu yapıcının aldığı son iki parametre ise, Grid
hücrelerine yerleştirilecek bileşenlerin arasındaki yatay ve dikey uzaklıkları
piksel olarak belirtmekte. Bu örneği geliştirdikten sonra Applet tagını
aşağıdaki gibi düzenledim.
<APPLET CODE="Layouts.class"
width="610" height="100">
</APPLET> |
Sonuç ise, FB (FB lilerin şampiyonluklarınıda
tebrik ederim bu arada) renkleriyle aşağıdaki gibi oluştu. BJK taraftarı olmama
rağmen, tasarımı böyle renklendirebildiğim için çok mutlu oldum. Demek ki,
Layout' ları bir arada kullanarak ve işin içine Panel bileşenlerini katarak daha
sağlam tasarımlar oluşturulabilirdi. Notepad ile dahi olsa. Ama bununla kim
uğraşırdıki güzelim JBuilder varken. (Elbette ben uğraşırdım sanırım.)

GridLayout sınıfınıda geçtim derken karşıma daha
karmaşık bir Layout sınıfı çıkıverdi. GridBagLayout. Bunu anlayabilmek için,
Bilim Teknik dergisinde her ay çıkan soruları çözer gibi kağıt kaleme sarılıp
çalışmam gerektiğini itiraf etmeliyim. GridBagLayout sınıfı ile, Applet üzerinde
çok karmaşık ekran tasarımlarını yapabilmek mümkün. Ancak bu işi başarabilmek
için bir o kadarda karışık bir teknik kullanmak gerekiyor. Burada önemli olan
nokta, Applet üzerine yerleşecek bileşenlerin X,Y koordinatları ile uzunluk ve
yükseklik bilgileri. Nitekim, GridBagLayout tekniğinde, Applet karelere
bölünüyor ve bileşenler bu kareler üzerine yerleştiriliyor. Şimdi burada
hakketten ele kağıt kalem almak ve çizmek lazım. Ancak dijital bir ortamda
olduğumuzu düşünürsek bu iş için, gelişmiş grafik programlarınıda
kullanabilirim. İşte bu amaçla bu Layout sınıfını kullanarak, Applet üzerinde
konumlandırılacak bir Button nesnesini göz önüne alarak basit bir çizim
oluşturdum.

Temel olarak yapacağım işlem buydu. Applet
ekranını karelere bölmek. Örneğin bir Button yerleştirmek istiyorum. Önceden bu
Button bileşenin X, Y koordinatlarını, uzunluk ve yükseklik bilgilerini,
yukarıdaki gibi bir şekli baz alarak bilmem gerekiyor. Olayın esprisi buydu
işte. Bu nedenle de GridBagLayout diğer Layout sınıflarına göre daha karmaşık
Applet tasarımları oluşturmamıza izin veriyordu. Çünkü bir ekran pozisyonlaması
için gereki 4 önemli unsuru baz alıyordu. X,Y Koordinatları, uzunluk ve
yükseklik. Peki bu zahmetli tasarımı kodlamada nasıl gerçekleştirebilirdim. Bu
amaçla epeyce bir saatimi, sırf GridBagLayout' un nasıl kullanıldığını anlamaya
harcadım. Sonuç olarak aşağıdaki gibi bir örnek geliştirdim.
import java.awt.*;
import java.applet.Applet;
public class Layouts extends Applet
{
TextField tf1;
TextField tf2;
Button bt1;
Label lb1;
Label lb2;
GridBagLayout gbl;
GridBagConstraints gbc;
public void init()
{
gbl=new GridBagLayout();
gbc=new GridBagConstraints();
setLayout(gbl);
gbc.insets=new Insets(2,2,2,2);
gbc.fill=GridBagConstraints.BOTH;
gbc.gridx=0;
gbc.gridy=0;
gbc.gridwidth=5;
gbc.gridheight=1;
lb1=new Label("Username");
gbl.setConstraints(lb1,gbc);
add(lb1);
gbc.gridx=6;
gbc.gridy=0;
gbc.gridwidth=5;
gbc.gridheight=1;
tf1=new TextField(25);
gbl.setConstraints(tf1,gbc);
add(tf1);
gbc.gridx=0;
gbc.gridy=1;
gbc.gridwidth=5;
gbc.gridheight=1;
lb2=new Label("Password");
gbl.setConstraints(lb2,gbc);
add(lb2);
gbc.gridx=6;
gbc.gridy=1;
gbc.gridwidth=5;
gbc.gridheight=1;
tf2=new TextField(25);
gbl.setConstraints(tf2,gbc);
add(tf2);
gbc.gridx=0;
gbc.gridy=3;
gbc.gridwidth=5;
gbc.gridheight=1;
bt1=new Button(" OK ");
gbl.setConstraints(bt1,gbc);
add(bt1);
}
} |
Kodları yazdıktan sonra önce Applet' in nasıl
çalıştığına baktım. Sonuç hiçte fena değildi.

Nasıl olmuştuda böylesine güzel bir sonuç elde
edebilmiştim. Herşeyden önce, GridBagLayout sınıfını oluşturdum. Ancak burada
GridBagConstraints isimli başka bir sınıf daha vardı. Bu sınıf, her bir bileşen
için gerekli X, Y koordinatları ile, uzunluk ve yükseklik ayarlamalarını
taşıyacak nesneler örneklendirmek amacıyla kullanılmaktaydı. Dolayısıyla bir
bileşeni, GridBagLayout sınıfı nesnesine eklerken setConstraints metodu ikinci
parametre olarak, GridBagConstraints sınıfına ait nesne örneğini almaktaydı.
Böylece, setConstraints metodunun ilk parametresinde belirtilen bileşen, Applet
üzerinde belirtilen X, Y koordinatlarına, belirtilen yükseklik ve uzunlukta
çiziliyordu. Burada uzunluk ve yükseklik piksel bazında değil hüce bazındadır.
Örneğin aşağıdaki satırları göz önüne alalım.
gbc.gridx=6;
gbc.gridy=1;
gbc.gridwidth=5;
gbc.gridheight=1;
tf2=new TextField(25);
gbl.setConstraints(tf2,gbc);
add(tf2); |
Burada TextField bileşeni, X=6, Y=1
koordinatlarına yerleştirilmiştir. Uzunluğu 5 hücre kadar, yüksekliği ise 1
hücre kadardır. Daha sonra, bu bileşen GridBagLayout nesnesine, setConstraints
metodu ile eklenmiştir. Artık, bu bileşeni Applet' e add metodu ile
eklediğimizde, GridBagLayout konumları esas alınacaktır.
gbc.insets=new Insets(2,2,2,2);
gbc.fill=GridBagConstraints.BOTH; |
Satırlarına gelince. Bu satırlarda,
GridBagConstraint nesnesinin bir takım özellikleri belirlenmektedir. Bunlardan
birisi insets özelliğidir. Insets ile, hücreler içindeki bileşenlerin hücrenin
kenarlarına olan uzaklığı belirtilmektedir. Bir başka deyişle boşluk miktarı.
Fill özelliği ileyse, GridBagLayout' un genişlemesi durumunda, hücre içi
bileşenlerin her yönde eşit şekilde genişlemesi belirtilmiştir.
Bu zor ama güçlü Layout' tan sonra, incelemeyi
unuttuğum bir Layout daha olduğunu farkettim. CardLayout. İlk başta iskambil
desteleri ile bir alakası olabilir mi diye düşündüm. Gerçektende öyleymiş.
CardLayout' ta, birbirlerinin üstüne binen katmanlar söz konusu. İşin güzel yanı
ise, CardLayout' lar ile, birbirinden farklı katmanların tasarlanabilmesi ve
çalışma zamanında bu katmanlardan sadece birisinin görünür olması. Dolayısıyla
bu katmanlar arasında gezinmek için, olay güdümlü programlama tekniklerini
kullanmak gerekiyor. Nasıl mı? İşte örnek.
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Layouts extends Applet implements ActionListener
{
TextField tf1;
TextField tf2;
Button bt1;
Button bt2;
Label lb1;
Label lb2;
Label lb3;
Panel p1;
Panel p2;
Panel p3;
Panel p4;
CardLayout iskambil;
public void init()
{
iskambil=new CardLayout();
p1=new Panel();
p2=new Panel();
p2.setBackground(Color.blue);
p3=new Panel();
p3.setBackground(Color.green);
p4=new Panel();
iskambil=new CardLayout();
p4.setLayout(iskambil);
lb1=new Label("Username");
p1.add(lb1);
tf1=new TextField(25);
p1.add(tf1);
lb2=new Label("Password");
p1.add(lb2);
tf2=new TextField(25);
p1.add(tf2);
bt1=new Button("Onceki");
bt1.addActionListener(this);
bt2=new Button("Sonraki");
bt2.addActionListener(this);
p2.add(bt1);
p2.add(bt2);
p4.add("Giris",p1);
p4.add("Diger",p3);
add(p4);
add(p2);
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand()=="Onceki")
{
iskambil.previous(p4);
}
else
if(e.getActionCommand()=="Sonraki")
{
iskambil.next(p4);
}
}
} |
Ve sonuç. CardLayout daha güzel bir tasarım sundu.
Tek bir applet sayfasında üst üste duran paneller arasında gezebilme imkanı.


Artık Layout' lara veda etme vakti geldi. Gelecek
kahve molalarında umarım JBuilder ile daha fazla ilgilenme fırsatı bulabilirim.
Katetmem gereken daha çok kilometre taşı var. Network programlama,
veritabanları, web servisleri, swing bileşenleri, windows uygulamaları vs...
Burak Selim ŞENYURT
selim@bsenyurt.com