Yazan : Şadi Evren ŞEKER

Bu yazının amacı, JAVA dilinde bulunan ve grafiksel kullanıcı ara yüzü geliştirmekte kullanılan SWING kütüphanesine hızlı bir başlangıç yapmaktır.

Öncelikle Swing kütüphanesinin gelişiminden hızlıca bahsedelim. Swing kütüphanesi JAVA diline JDK 1.1 sürümünden sonra eklenmiştir. Daha önce AWT (Active Window Toolkit) ismi verilen bir kütüphane kullanmaktaydık ancak çok daha fazla ve gelişmiş özelliklerle gelen swing kütüphanesi neredeyse tamamen AWT yerine geçti denilebilir. AWT halen kullanılmakta, bunun en büyük sebebi JAVA’nın Visual Studio gibi geliştirme ortamlarından farklı olarak geçmişle uyumlu olmasıdır (back compatibility). Yani, örneğin 1997 yılında yazdığım bir kodu hala derleyip çalıştırabiliyorum.

AWT’nin bulunmasındaki diğer önemli bir faktör ise, Swing kütüphanesinin AWT üzerinde geliştirilmiş olmasıdır. AWT’den bu kadar bahsettikten sonra son olarak aynı projede hem AWT hem de Swing kullanmamanız gerektiğini, aksi halde ağır ve hafif bileşenlerin ekranda hatalı görüleceğini (heavy weighted, light weighted) söyleyerek Swing kütüphanesini anlatmaya başlayalım.

Swing kütüphanesi, javax altında bulunmaktadır ve bütün swing sınıfları (classes) javax.swing paketi ile başlar.

Örneğin, ekrana basit bir düğme koyarak uygulama geliştirmeye başlayalım.


Yukarıdaki kodun çıktısı, aşağıdaki şekilde bir pencereye yerleştirilmiş bir düğmeden (button) ibarettir:


Kodumuzda kullandığımız iki swing bileşeni olan JFrame ve JButton import edildikten sonra sınıfın bir JFrame olacağını, extedns JFrame yazıp JFrame sınıfını kalıtımla (inheritance) alarak belirtiyoruz.

Kodumuzda bulunan iki metottan ilki bir inşa fonksiyonu olup (constructor), this.add fonksiyon çağrılması ile JFrame içinde tanımlı olan add fonksiyonuna bir adet JButton parametre verilmiştir.

Klasik olarak swing kütüphanesinde, bir bileşenin diğer bileşenleri içinde barındırma özelliği bulunuyorsa (container) bu durumda add fonksiyonu, parametre olarak aldığı bileşeni, barındırıcı bileşene eklemektedir.

Kodun 5. satırında yapılan bu ekleme işleminde dikkat edilecek bir husus da, JButton bileşenini oluşturan ve new ile çağrılan yapıcı fonksiyonun (constructor) parametre olarak bir dizgi (string) almış olmasıdır. Bu dizgi, düğmenin üzerinde görülecek olan yazıdır.

Son olarak main fonksiyonunda, yeni tanımladığımız bu sınıftan bir nesne (object) oluşturarak bu objenin referansına sb ismini veriyoruz. Kodun 9. ve 10. satırlarında ise sırasıyla sb isimli bu nesneyi (ki artık JFrame özelliği taşıyan ve içerisinde bir buton olan nesnedir) paketliyoruz ve göstertiyoruz. Paketleme işlemini basitçe, bir pencerenin içerisindeki bileşenlerin sığacağı en ufak hali alması olarak düşünebilirsiniz. Gösterme işlemi ise bir bileşenin görünürlülüğünü (visibility) doğru yapmaktan ibarettir (true). Tersi şekilde görünürlülüğü yanlış (false) yapılarak bir bileşen gizlenebilir. Yine daha önceki sürümlerde bu işlem için sırasıyla show() ve hide() fonksiyonları da kullanılmaktaydı ancak JDK 1.3 sonrasında bu fonksiyonlar kaldırıldı.

Şimdi gelelim bu düğmenin tıklanması halinde eylemi algılamaya.

Yukarıdaki kodu yazıp denediyseniz tıklama eyleminin herhangi bir sonuç doğurmadığını görmüşsünüzdür. Bunun sebebi JAVA dilinde tanımlı olan herhangi bir eylemin sınıf içerisinde yer alamamasıdır.

JAVA dilinde eylemi üreten ve yakalayan nesneler farklı olabilir. Örneğin yukarıdaki örnekte düğmeyi tanımladığımız swingbuton isimli sınıf düğmeye tıklandığında devreye girebileceği gibi tamamen başka bir sınıf da devreye sokulabilir. Biz basit olsun diye ilk örneğimizde yine aynı sınıfta eylemi yakalayacağız. Bunun için öncelikle sınıfa bu özelliğin kazandırılması gerekir. JAVA dilinde bir sınıfın herhangi bir bileşen ile ilgili bir eylem yakalayabilmesi için ActionListener olması gerekir.

public class swingbuton extends JFrame implements ActionListener

 
 

şeklinde sınıfın tanımını değiştirerek bu sorunu çözebiliriz. Ancak, arayüzlerden (interface) hatırlanacağı üzere bir arayüzü (interface) sınıfa kazandırmanın (implements), bağlayıcı bir sonucu olmaktadır.


Kodumuzda yeni olan en büyük fark, sınıfta artık ActionListener arayüzünün implement edilmesidir. Bu arayüzün sınıfa uygulanması ile birlikte, sınıfta ” actionPerformed” isimli fonksiyonu bulundurma zorunluluğu ortaya çıkar. Nitekim yukarıdaki kodun 10-12. satırları arasında bu fonksiyon kodlanmış ve herhangi bir eylem olması halinde çalışacak olan bu fonksiyonun içerisinde ekrana “butona basıldı” mesajının yazılması sağlanmıştır.

Diğer bir ilave ise artık düğmenin bir eylem dinleyicisi olmasına olan ihtiyaçtır. Düğmemize basıldığında hangi sınıfın bu eylemi yakalacağını kodda belirtmemiz gerekir ki bu durum da 8. satırda kodlanmıştır.

Yukarıdaki kodun ekran çıktısı aşağıdaki şekildedir:


Birden fazla düğme bulunması halinde düğmeleri ayırt etmek için eylemin özel olarak koşullandırılması gerekir.


Kodun yeni halinde, düğmelerin tanımlandığı satırı sınıf geçerlilik alanına alarak actionPerformed fonksiyonu içerisinde hangi düğmeye tıklandığını kontrol edebiliyoruz. Bunun için parametre olarak gelen ActionEvent tipindeki e nesnesinin kaynağını okutan .getSource metodunu çağırıyor ve hangi nesneye eşit olduğunu sorguluyoruz.

Ayrıca kodda yapılan yeni bir ilave, birden fazla bileşeni aynı anda ekranda gösterebilmek için bir yayılım (Layout) eklenmesidir. Yukarıdaki kodda, 10. satırda bulunan komut, this ile ifade edilen JFrame nesnesinin yayılımının FlowLayout tipinde olacağını belirtmektedir. Bunun anlamı eklenen her bileşen, bir öncekinin sağına ilave edilecek, nihayet ekranda daha fazla sağa eklenecek yer kalmayınca aşağıya geçileceğidir.


Swing kütüphanesi kullanılarak mevcut bileşenler, yukarıda gösterildiği şekilde ekrana eklenip kullanılabileceği gibi, bileşenler üzerinde değişiklik yapılması da mümkündür. Örneğin bir swing bileşeni olan Jpanel üzerinde çizim yapmaya çalışalım:

 
 


Yukarıdaki kodda bulunan sınıf, Jpanel bileşenini miras almış ve bu bileşenin “paintComponent” isimli metodunun üzerine ezmiştir (override). Neticede Jpanel jf isimli Jframe’e eklenmiş ancak yeni çizim özellikleri ile görüntülenmiştir. Kodun ekran çıktısı aşağıdaki şekildedir:


paintComponet fonksiyonu yukarıda gösterildiği şekilde ezilerek (override) Graphics kütüphanesinden istenilen bir nesne, yukarıda gösterildiği şekilde ekrana eklenebilir.

Ayrıca JAVA’nın kuvvetli kütüphanelerinde birisi de Graphics2D kütüphanesidir. 2 boyutlu şekillerin bulunduğu kütüphane olarak tanımlayabileceğimiz bu kütüphane ile görsel pek çok işlem yapılabilir. Bu kütüphaneyi kullanmak için örnek kod aşağıda verilmiştir:


Yukarıdaki yeni kodda, paintComponent fonksiyonu altında, Graphics2D sınıfından türetilmiş bir nesne olan g2d nesnesine, şimdiye kadar kullandığımız ve klasik Graphics kütüphanesinin bir nesnesi olan g nesnesini tip inkılabı ile (type casting) atıyoruz. Bu sayede g2d nesnesinin fonksiyonlarını kullanabiliyoruz.

Kodda, dikdörtgen ve daire şeklinde iki nesne ekrana eklenerek gösterilmiştir. Kodun çıktısı aşağıda verilmiştir:

 
 


Aynı ekranda hem çizim hem de bileşen (component) kullanan kod (Ahmet beyin sorusu üzerine ekliyorum):

Sorunumuz, aynı ekranda hem çizim yapabilmek, yani Graphics kütüphanesini kullanmak, hem de java’nın bileşenlerinin (örneğin düğme (buton) veya yazı alanı (text areat) gibi ) kullanabilmek.

Bunu yapan örnek bir kodu aşağıdaki şekilde kodlayabiliriz:


Kodda, öncelikle bir JPanel sınıfı oluşturuyoruz. Basitçe JPanel miras alan bir sınıfımız var, ismi cizim ve bu sınıf içerisinde, yukarıda da anlatılan paintComponent metodunun üzerine ezere (method overriding) Graphics kütüphanesini kullanıyoruz (örnek olarak bir çizgi çizdirilmiştir).

Ardından main fonksiyonumuzu içeren bir sınıf kodlanmıştır. Bu sınıf içerisinde x nesne atıfı (object referrer) ile gösterilen bir JFrame oluşturulmuş ve bileşen yayılımı (layout) GridLayout olarak ayarlanmıştır. Kabaca ekran 2×2 boyutlarında dört parçaya bölünmüştür. Javada bu yayılıma ekleme yapıldığında sol üst köşeden başlanarak bileşenler eklenir ve ilk satır bitince aşağıya geçilir.

Buna göre sırasıyla eklediğimiz bileşenler, c ismindeki ve cizim sınıfından türetilmiş bir JPanel, satır içinde (inline) olarak türetilmiş bir cizim nesnesi, üzerinde “deneme” yazan bir düğme (buton) ve içinde “www.bilgisayarkavramlari.com” yazılı bir yazı alanı (JTextArea).

Ekranın çıktısı aşağıdaki şekildedir:


Görüldüğü üzere, ekranda çizim içerikli iki panel ve iki adet swing kütüphanesinden bileşen eklenmiştir.

   

Yorumlar

  1. Ahmet

    Hocam! Benim bir sorum var. Aynı pencerede hem çizim yapabilmek hem de o pencereye bazı componentler eklemek istiyorum. Yukarıda yaptığınız son örneğe benzer bir örnek yaptım. frame in layout una “null” dedim ama componentler görünmedi. frame min layout nuna “null” dan farklı bir değer verdiğimde ise componentler görünüyor, ama pencerede yaptığım çizimler görünmüyor. Bunun sebebi nedir acaba????

  2. fethi

    öncelikle teşekkür ediyorum harika bir mekale..fakat super.paintComponent(g); satırılarını anlayamıyorum bir açıklama eklerseniz çok sevinirim..java da yeniyim teşkkurler 🙂

  3. Şadi Evren ŞEKER Article Author

    Sanırım son kodda bulunan 6. satırı kast ediyorsunuz. Basitçe şu şekilde anlatabiliriz.

    Öncelikle içinde bulunduğumuz sınıf (class) tanımına bakalım (kodun 4. satırı) Burada sınıfımız cizim ismiyle tanımlanmış ve JPanel sınıfını extend etmiş, yani miras almış (inheritance).

    Bu da demek oluyor ki bu kodda herhangi bir yerde super kelimesi görürseniz bir üstteki sınıf olan JPanele bir atıf yapılıyordur.

    O halde buradaki super.paintComponent() fonkisyonu JPanel sınıfından bize gelen bir fonksiyon olacaktır. Nitekim de öyledir ve biz burada JPanel’in içerisinde çizim yapacağımız için bu fonksiyona şu anda tanımlı olan g değişkenimizi parametre olarak veriyoruz.

    Burada yapılan aslında atıf ile çağırmak (Call by reference) olarak düşünülebilir. Yani bir nesnenin referansını parametre olarak geçiriyoruz ve JAVA’ya diyoruz ki bundan sonra g değişkeninde yapılan herşey aslında JPanel’in çizim özelliklerine yapılmaktadır.

  4. yılmaz

    çok açıklayıcı ve bilgilendirici bir yazı olmuş elinize sağlık..swing konusunda daha fazla örnekler de eklerseniz çok memnun oluruz

  5. Onur Işık

    Merhabalar,

    İlk önce vermiş olduğunuz emek için size teşekkür ediyorum.Benim anlamadığım birşey var;yanlış anlamamışsam sınıfın ismini yazdıktan sonra “extends JFrame yada Applet veya JApplet” diye sınıfın ne içerdiğini belirtiyoruz ama bazı örneklerde aşağıda “public static void main(String args[])… yazılıdığınıda görüyorum.Ne zaman yazıp yazmayacağımızı nasıl bilebiliriz??Yada çok rica etsem ne zaman JFrame Yada JApplet yazacağımız hakkında mümkünse biraz detaylı bilgi verebilir misiniz?Tek başıma öğrendiğim için bazı şeyleri anlamam zor oluyorda 🙂

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir