Professional Documents
Culture Documents
Java ile görsel programlama için mevcut en yaygın yol: Swing (Diğer alternatifler: JavaFX, SWT, AWT).
SWT ve AWT öğrenmek, bu vakitten son önemli değil. Topluluk, artık JavaFX’e yönleniyor. Yine de Swing’e
derinlemesine girmeksizin bizim anlatacağımız kadar kısmını öğrenmek size çok şey katacaktır. Swing kütüphanesinin
çok küçük ama yeterli bir kısmını göreceğiz. Bu sayede nesneye dayalı programlamanın en önemli kavramlarını
öğreneceksiniz.
JFrame için:
JPanel için:
JPanel tepsi = new JPanel(duzen); // duzen yerine örneğin şu gelir: new GridLayout(3,4,5,5)
// 3 satır, 4 sütun; bileşenler arasında 5 piksel yatay boşluk, 5 piksel dikey boşluk.
// Dolayısıyla bu örnekte tepsiye 12 bileşen eklenir.
tepsi.setBackground(renk); // Tepsinin arka plan rengi değiştirilebilir. renk yerine:
Color.RED gibi renk sabitlerinden biri
Ya da new Color(50,100,200) gibi kendi istediğiniz bir renk gelecek.
[0,255] aralığında sırasıyla kırmızı, yeşil, mavi (RGB) renk ağırlıkları girilir.
tepsi.add(bilesen); // Tepsiye bir bileşen eklenir.
Başka bir JPanel ya da JButton, JLabel, JTextField gibi bir bileşen gelecek.
Bileşenler, satır dolana kadar soldan sağa doğru eklenir. Satır dolunca otomatik olarak bir alt satıra inilir.
JLabel için:
Oluşturulması, içeriğinin değiştirilmesi, içeriğinin okunması, yazı renginin değiştirilmesi ve arka plan renginin
değiştirilmesi tıpkı JLabel için olduğu gibi.
JLabel’da daha çok setText kullanılır (yazıyı biz belirlediğimiz için getText daha az kullanılır), JTextField’da daha çok
getText kullanılır (yazıyı kullanıcı belirlediği setText daha az kullanılır).
JButton için:
Oluşturulması, içeriğinin değiştirilmesi, içeriğinin okunması, yazı renginin değiştirilmesi ve arka plan renginin
değiştirilmesi tıpkı JLabel ve JTextField için olduğu gibi.
Şart değil ama işini çok kolaylaştıracak kurallar (Biz bu kuralları takip edeceğiz):
1. Kullanılacak JFrame, JPanel, JLabel, JButton, JTextField örneklerini yerel değişken olarak değil de, sınıf değişkeni
olarak tanımla.
2. main metodunda yapılacak işleri, kendi tanımlayacağın parametresiz void metotlara paylaştır (Bütün değişkenler
sınıf değişkeni olduğu için parametreye ve değer döndürmeye gerek yok).
ÖRNEK BİR PROGRAM (1. YAKLAŞIM)
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
Çalışırıp deneyin!
İkinci yaklaşım (Bunun da mantığını bilmek çok önemli. Yoksa nesneye dayalı programlama anlaşılmaz!):
Sınıfı extends JFrame şeklinde tanımlayın. Yani sınıfın kendisi, bir çeşit JFrame olacak.
main metodunda yazdıklarımızı kurucu metoda yazın.
main metoduna SinifAdi pencere = new SinifAdi(); ya da kısaca new SinifAdi(); yazın.
Yeni main metodu dışında kodda pencere kelimesini kullanmayacaksınız artık. Örneğin
pencere.setContentPane(), pencere.setVisible() yerine setContentPane(), setVisible() kullanacaksınız. Çünkü
zaten pencere’nin içindesiniz!
Artık static çalışmıyoruz! [main hep statictir, o hariç] İşte nesneye dayalı programlama!
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GorselProgram extends JFrame { // Bu sınıfın kendisi bir penceredir. Başka bir pencereye gerek yok!
private static JFrame pencere;
private static JPanel tepsi;
private static JLabel yazi1, yazi2, yazi3;
private static JTextField yaziKutusu1, yaziKutusu2;
private static JButton dugme;
public static void main(String[] args) { // Program çalıştığında sınıfımızdan bir nesne üretelim
new GorselProgram(); // Yeni bir nesne oluşturmamız yeterli. İsim bile vermemize gerek yok.
pencereyiOlusturupTepsiEkle();
tepsiyeBilesenleriEkle();
dinleyicileriEkle();
pencereAyarlariniYap();
}
public GorselProgram() { // new GorselProgram() dendiği an yapılması gereken her şey burada.
pencereyiOlusturupTepsiEkle();
tepsiyeBilesenleriEkle();
dinleyicileriEkle();
pencereAyarlariniYap();
}
x yerine ne gelmeli?
“implements ActionListener” olan (ActionListener interfaceini implement eden) bir sınıftan üretilmiş bir nesne.
Böyle bir interfaceimiz olsun. KonsolaYazilabilir ky = new KonsolaYazilabilir(); şeklinde bir kod yazılamaz. Çünkü
interfacelerden nesne üretilmez, sınıflardan nesne üretilir! Zaten böyle nesne mi olur? Orada bir metot var ama metot
kendisinin nasıl çalışacağını bilmiyor!
public Sayi(double s) {
sayi = s;
}
}
Şimdi şunu yazabiliriz:
veya
E o zaman bu interface ne işe yarıyor? O hiç olmasa, sınıfta yine konsolaYaz metodunu tanımlasak olmaz mı?
Burada olur tabii ama asıl problemimizde olmaz. Adam sizden, public void actionPerformed(ActionEvent ae) metodu
barındıran bir nesne istiyor. Bunu söylemenin yolu şu: Gidip mesela ActionListener adında bir interface tanımlar. İçine
bu metodu yazar.
1. SEÇENEK: O interfacei implement eden bir sınıf ayrıca tanımla ve o sınıftan oluşturduğun nesneyi parametre olarak
ver.
public class AmanYaBirSinifDahaCikti implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
String isim = yaziKutusu1.getText();
String yas = yaziKutusu2.getText();
String mesaj = isim + ", " + yas + " yaşındadır.";
yazi3.setText(mesaj);
}
}
Ama şimdi burada HATA var. Adam, yaziKutusu1, yaziKutusu2, yazi3 nedir bilmiyor ki!?
@Override
public void actionPerformed(ActionEvent ae) {
String isim = yaziKutusu1.getText();
String yas = yaziKutusu2.getText();
String mesaj = isim + ", " + yas + " yaşındadır.";
yazi3.setText(mesaj);
}
}
Zor oldu ama oldu. Başka sınıfa gittiğimiz için gerekli nesneleri de taşımamız gerekti.
Peki bu sınıfı nasıl kullanacağız?
public class SeninProgramin {
…
private static void dinleyicileriEkle() {
AmanYaBirSinifDahaCikti x = new AmanYaBirSinifDahaCikti(yaziKutusu1, yaziKutusu2, yazi3);
dugme.addActionListener(x);
}
…
}
Bu kadar. Ya da:
public class SeninProgramin {
…
private static void dinleyicileriEkle() {
dugme.addActionListener( new AmanYaBirSinifDahaCikti(yaziKutusu1, yaziKutusu2, yazi3) );
}
…
}
Ama şöyle parlak bir fikrimiz gelmiş olabilir. Biz zaten bir sınıftayız. Madem o interfacei implement eden bir sınıfa
ihtiyacımız var, bu sınıf implement etsin olsun bitsin. Hem nesneleri (yazı kutuları ve yazılar) taşımamıza da gerek
kalmaz! [Bu durumda programın 2. yaklaşımını yani JFrame extends edip static’ten kurtulmalı, this’e kavuşmalıyız]
@Override
public void actionPerformed(ActionEvent ae) {
String isim = yaziKutusu1.getText();
String yas = yaziKutusu2.getText();
String mesaj = isim + ", " + yas + " yaşındadır.";
yazi3.setText(mesaj);
}
Bu son yaptığımız çok hoş, ama birden fazla düğmemiz olsaydı işe yaramazdı. Çünkü aynı sınıfa bir actionPerformed
metodu daha tanımlayamayız, çakışırlar (Ama yine de mantığını anlamak çok önemli!).
2. SEÇENEK: O interfacei implement eden bir sınıfı satır içinde (isimsiz olarak) tanımla ve bir nesne oluştur.
Yani programda yaptığımız gibi:
new InterfaceAdi() {
@Override
metot1(Parametreler) {
…
}
@Override
varsaMetot2FalanDiyeGider(Parametreler) {
…
}
}
3. SEÇENEK: En güzel ama öğrenmek için şimdilik erken olan yol (Şimdi diğer yöntemleri anlamak çok önemli):
Java 8 ile gelen lambda expressions!