Egy programban a gomb megnyomására szokott történni valami! A mi programunk meg semmit nem csinál.
Tulajdonképpen furán nem csinál semmit: hiszen úgy tűnik, hogy a programnak vége lesz, de az ablak még mindig kinn marad a képernyőn. Hogy is van ez?
Az történik, hogy az első ablak megnyitásával elindul egy eseménykezelő háttérprogram. Ez a program olyan, mint egy jó tündér: figyeli, hogy mit csinálsz az egérrel és a billentyűzettel. Minden egér elmozdítás, kattintás az egy esemény. Természetesen minden gombnyomás is egy esemény.
Ezeket az eseményeket az eseménykezelő eljuttatja a JFrame példányunknak, ami ezeket továbbítja a benne lévő többi widgetnek, ha szükséges. Például, ha a JFrame üres területére kattintasz, akkor a kattintási eseményt megkapja a frame. De ha a gomb fölött kattintasz, akkor a frame tudja, hogy az egér alatt épp egy gomb van, és a gombnak továbbadja a kattintási eseményt.
Végül az események picit megváltoztatják a widgeteket. Ha kattintasz, akkor a gomb benyomódni látszik. Eddig szuper, minden automatikusan megy, de hogy tudjuk megcsinálni, hogy erre valamit csináljon a programunk?
Az eseményekre eseményfeldolgozót (listener - azaz "hallgatózó") lehet írni, ilyen egyszerű! Az lenne a legjobb, ha a listener egy metódus lenne, ami "magától" meghívódik, ha valaki kattintott a gombra.
Egy a baj. A Javaban minden objektum... nem pedig metódus. Metódust nem lehet átadni paraméternek.
public class HelloGui {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setSize(200, 100);
frame.setTitle("Elso program");
frame.setVisible(true);
frame.setLayout(null);
JLabel label=new JLabel("Gipsz Jakab");
frame.add(label);
label.setBounds(5, 0, 100, 21);
JButton button=new JButton("Ok");
frame.add(button);
button.setBounds(5, 25, 75, 21);
// Ez nem megy
button.addActionListener(csinald);
}
public static void csinald() {
// ha megnyomjak a gombot
System.out.println("Katt!");
}
}
Helyette egy kicsit kacifántosabb a megoldás:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
csinald();
}
});
Azaz... a buttonnak van egy addActionListener metódusa. Természetesen ez is egy konténer, így ha akarjuk, több listenert is köthetünk a gombra, így a kattintáskor az összes meghívódik majd. A listener maga pedig egy ActionListener osztály példánya - mert objektumot át lehet adni paraméternek. Azért hogy azt csinálja amit mi szeretnénk, override-oljuk az actionPerformed metódusát, amit akkor hív meg, amikor megnyomják a gombot. Végül ebben a metódusban már bármit csinálhatunk, például meghívhatjuk bármely más metódust. Ami azt illeti, ez az actionPerformed egy normális metódus saját maga is, így akár itt is kiírhatunk valamit a konzolra:
public class HelloGui {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setSize(200, 100);
frame.setTitle("Elso program");
frame.setVisible(true);
frame.setLayout(null);
JLabel label=new JLabel("Gipsz Jakab");
frame.add(label);
label.setBounds(5, 0, 100, 21);
JButton button=new JButton("Ok");
frame.add(button);
button.setBounds(5, 25, 75, 21);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Katt!");
}
});
}
}
Feladat: Próbáld ki! Kattintáskor a Console View-en megjelenik, hogy Katt!
Nem kell.
Feladat: töröld ki az actionListeneres részt, és kezd újra. Kövesd a következő lépéseket:
és máris készen van az egész váz:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
});
Ennyi volt, így már elég könnyű, igaz?
Sok fajta van! ActionListenere szinte minden widgetnek van, ez hívódik meg, ha rákattintasz. De van MouseListener is - ezzel az egér megnyomását, elengedését, a widget fölé húzását is el lehet kapni. A MouseMotionListener-rel pedig az egér mozgási eseményeit lehet elkapni.
A listenerekben általában van valami paraméter - az ActionListener esetén az ActionEvent típusú e nevű osztály. Ennek sok értelme nincs, de mondjuk a MouseMotionListener-nél a paraméter tartalmazza az egér pozíciójának koordinátáit, ami hasznos lehet.
Feladat: csináld meg, hogy amikor a gombon az egeret lenyomják, írja ki hogy "Megnyomva", amikor elengedik, akkor meg hogy "Elengedve". Tipp: MouseListener.
Feladat: csináld meg, hogy amikor az egeret mozgatják a gomb felett, akkor írja ki az egér x és y koordinátáit.
Mikor ezt olvasod, a Java 8-as verziója lesz az elfogadott mindenhol. Ebben van egy érdekes nyelvi bővítés - a funkcionális programozás -, amit fel lehet használni arra, hogy a listenereket egyszerűbben írjuk meg.
// Java 8 előtt
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Katt!");
}
});
// Java 8
button.addActionListener(e -> {
System.out.println("Katt");
});
Ezt az írásmódot azonban csak akkor lehet használni, ha a listener egyféle metódussal rendelkezik (pld. ActionListener). Ha a listenernek többféle metódusa lenne (mint például MouseListener), akkor ez nem megy sajnos, ezért a jövőben maradunk a régi fajta írásmódnál, okés?
Ennyi előkészület után igazán megtehetnénk, hogy ne a konzolra írjunk, hanem változtassuk meg az ablakban a label szövegét, nem?
public class HelloGui {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setSize(200, 100);
frame.setTitle("Elso program");
frame.setVisible(true);
frame.setLayout(null);
JLabel label=new JLabel("Gipsz Jakab");
frame.add(label);
label.setBounds(5, 0, 100, 21);
JButton button=new JButton("Ok");
frame.add(button);
button.setBounds(5, 25, 75, 21);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// semmi System.out.println!
label.setText("Katt!");
}
});
}
}
Ez igazán nem volt nehéz, ugye?
Feladat: csináld meg, hogy a gombra kattintva a gomb elugrik egy véletlen pozícióba! A button.setLocation-al tudod a helyét megváltoztani, a Random-ot meg a konténeres részben már használtad.