[[:oktatas:programozás:java|< Java]]
====== Java eseménykezelés ======
* **Szerző:** Sallai András
* Copyright (c) 2011, Sallai András
* Szerkesztve: 2011, 2013, 2014, 2015, 2019
* Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]]
* Web: https://szit.hu
===== Bevezetés =====
A Java grafikus felületein többféle esemény, többféle módon kezelhető.
Az eseménykezeléshez használhatunk interfészeket és/vagy osztályokat.
Az osztályokat használhatjuk "névtelenül".
===== Eseménykezelés példa =====
A következő példában ablak eseményeire reagálunk. Két eseménykezelőt használunk; egyik a **WindowsListener**, a másik az **ActionListener**. A WindowListener és az ActionListener is egy interfész, amit a implementálunk
a Esemeny osztályunkon.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Esemeny extends JFrame implements WindowListener, ActionListener {
JTextField edit;
JButton gomb;
private int szamlalo = 0;
public static void main(String[] args) {
esemeny ablak = new esemeny("Az első ablakom");
ablak.setSize(350,100);
ablak.setVisible(true);
}
public Esemeny(String title) {
super(title);
setLayout(new FlowLayout());
edit = new JTextField(20);
gomb = new JButton("Kattints ide");
add(gomb);
add(edit);
addWindowListener(this);
gomb.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
szamlalo++;
edit.setText("A gomb le lett nyomva " + szamlalo + " -szer");
}
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
public void windowOpened(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
}
A nyelv megköveteli egy interfaceben deklarált függvények definiálását használatkor. Ezért
a következő függvényeket akkor is le kell írnunk, ha nem használjuk azokat:
public void windowOpened(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
Ilyenkor a függvény törzsét üresem hagyom, csak egy {} karakterek szerepelnek.
===== Eseményfigyelők =====
Számtalan eseménykezelő áll rendelkezésünkre a java.awt és a javax.swing csomagban is.
==== AWT ====
^ Eseményfigyelő ^ Figyelő metódus ^ Regisztrálva a következő komponenseknél ^
| ActionListener | actionPerformed() | AbstractButton, Button, ButtonModel, ComboBoxEditor, JComboBox, JFileChooser, JTextField, List, MenuItem, TextField, Timer |
| AdjustmentListener | adjustmentValueChanged() | Adjustable, JScrollBar, Scrollbar |
| ComponentListener | componentHidden(), componentMoved(), componentResized(), componentShown() | Component |
| ContainerListener | componentAdded(), componentRemoved() | Container |
| FocusListener | focusGained(), focusLost() | Component |
| ItemListener | itemStateChanged() | AbstractButton, ButtonModel, Checkbox, CheckboxMenuItem, Choice, ItemSelectable, JComboBox, List |
| KeyListener | keyPressed(), keyReleased(), keyTyped() | Component |
| MouseListener | mouseClicked(), mouseEntered(), mouseExited(), mousePressed(), mouseReleased() | Component |
| MouseMotionListener | mouseDragged(), mouseMoved() | Component |
| TextListener | textValueChanged() | TextComponent |
| WindowListener | windowActivated(), windowClosed(), windowClosing(), windowDeactivated(), windowDeiconified(), windowIconified(), windowOpened() | Window |
==== Swing ====
^ Eseményfigyelő ^ Figyelő metódus ^ Regisztrálva a következő komponenseknél ^
| AncestorListener | ancestorAdded(), ancestorMoved(), ancestorRemoved() | Action, JComponent |
| CaretListener | caretUpdate() | JTextComponent |
| CellEditorListener | editingCanceled(), editingStopped() | CellEditor, |
| ChangeListener | stateChanged() | AbstractButton, BoundedRangeModel, ButtonModel, JProgressBar, JSlider, JTabbedPane, JViewport, MenuSelectionManager, SingleSelectionModel |
| HyperlinkListener | hyperlinkUpdate() | JEditorPane |
| InternalFrameListener | internalFrame- Activated (), internalFrameClosed(), internalFrameClosing()internalFrame- Deactivated(), internalFrame- Deiconified(), internalFrame- Iconified()internalFrameOpened() | |
| ListDataListener | contentsChanged(), intervalAdded(), intervalRemoved() | AbstractListModel, ListModel |
| ListSelectionListener | valueChanged() | JList, ListSelectionModel |
| MenuDragMouseListener | menuDragMouseDragged(), menuDragMouseEntered(), menuDragMouseExited(), menuDragMouseReleased() | JMenuItem |
| MenuKeyListener | menuKeyPressed(), menuKeyReleased(), menuKeyTyped() | JMenuItem |
| MenuListener | menuCanceled(), menuDeselected(), menuSelected() | JMenu |
| PopupMenuListener | popupMenuCanceled(), | JPopupMenu |
| | popupMenuWillBecome- | |
| | Invisible(), | |
| | popupMenuWillBecome- | |
| | Visible() | |
| TreeExpansionListener | treeCollapsed(), treeExpanded() | JTree |
| TreeSelectionListener | valueChanged() | JTree |
| TreeWillExpandListener | treeWillCollapse(), treeWillExpand() | JTree |
| java.beans.PropertyChangeListener | propertyChange() | Action, JComponent, UIDefaults, UIManager |
| java.beans.VetoableChangeListener | vetoableChange() | JComponent |
===== Billentyűzet figyelése =====
Háromféle esemény figyelhetünk:
* keyType - karakterként azonosítható billentyű lett leütve
* keyPressed - egy billentyűt lenyomtak
* keyReleased - egy billentyűt felengedtek
Többek között, a kurzormozgatók és a funkcióbillentyűk nem
váltanak ki keyType eseményt.
A keyPressed és a keyReleased esemény esetén a KeyEvent változóból
a billentyűkódja olvasható ki. A keyType esemény esetén az
billentyűhöz tartozó karakter lekérdezhető.
A következő példában a keyType eseményt kezeljük, majd reagálunk az "a" és a "b"
billentyűk leütésére.
import java.awt.event.*;
import javax.swing.*;
class Program extends JFrame implements KeyListener {
JFrame ablak;
JButton gomb;
public static void main(String args[]) {
new Program();
}
Program() {
gomb = new JButton("Teszt");
add(gomb);
setBounds(0,20,100,50);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
setFocusable(true); //Szükséges a lenyomott billentyű figyeléséhez
setVisible(true);
}
public void keyTyped(KeyEvent e) {
char i = e.getKeyChar();
String str = Character.toString(i);
if(i == 'a')
gomb.setText("a");
if(i == 'b')
gomb.setText("b");
}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {}
}
Vegyük észre, hogy engedélyezni kell az ablakon a fókuszt, ahhoz, hogy billentyűleütéseket tudjunk figyelni.
Újabb példa:
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
class Program extends Frame {
Program() {
addKeyListener(new BillentyuKezeles());
addWindowListener(new AblakKezeles());
setSize(400, 300);
setVisible(true);
}
class BillentyuKezeles implements KeyListener {
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_A : setTitle("a"); break;
case KeyEvent.VK_B : setTitle("b"); break;
case KeyEvent.VK_C : setTitle("c"); break;
case KeyEvent.VK_1 : setTitle("1"); break;
case KeyEvent.VK_2 : setTitle("2"); break;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
class AblakKezeles extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
new Program();
}
}
==== A KeyEvent osztály mezői ====
A KeyEvent osztályban több állandó van definiálva, amelyek megkönnyítik a billentyűkódok
vizsgálatát. Az alább táblázatokban a teljesség igénye nélkül találunk néhány állandót.
^ Funkcióbillentyűk ^^
| VK_F1 | VK_F2 |
^ Kurzormozgatók ^^^^^^^^^
| VK_HOME | VK_END | VK_INSERT | VK_LEFT | VK_RIGHT | VK_UP | VK_PAGE_DOWN | VK_PAGE_UP | VK_DOWN |
^ Váltók ^^
| VK_TAB | VK_SHIFT | VK_META | VK_ALT |
^ Numerikus ^^^
| VK_NUMPAD1 | VK_NUMPAD2 | stb.... |
^ Számok ^^^
| VK_1 | VK_2 | stb....|
^ Egyéb ^^^
| VK_SPACE | VK_PAUSE | VK_DELETE |
A kontroll billentyű (Ctrl) figyelésére is lehetőségünk van.
A KeyEvent objektumon a getExtendedKeyCode() metódus tájékoztat
a kontrollbillentyű lenyomásáról.
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.Color;
class Program01 extends JFrame {
JPanel panel;
Program01() {
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
OnKeyPressed(e);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
});
panel = new JPanel();
panel.setBounds(10, 300, 100, 30);
panel.setBackground(Color.green);
add(panel);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 400);
setVisible(true);
}
private void OnKeyPressed(KeyEvent e) {
System.out.println(e.getExtendedKeyCode());
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("Enter");
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
System.out.println("Jobbra");
}
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
System.out.println("Balra");
}
System.out.println(e.getKeyCode());
}
public static void main(String args[]) {
new Program01();
}
}
Egy panel mozgatása, jobbra, balra (indítás Enter):
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.Point;
class Program01 extends JFrame {
JPanel panel;
Timer timer;
enum TDirection {left, right}
TDirection direction = TDirection.left;
Program01() {
timer = new Timer (10, new ActionListener() {
public void actionPerformed(ActionEvent e) {
MehetIdozitoActionEvent(e);
}
});
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
OnKeyPressed(e);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
});
panel = new JPanel();
panel.setBounds(10, 300, 100, 30);
panel.setBackground(Color.green);
add(panel);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 400);
setVisible(true);
}
private void MehetIdozitoActionEvent(ActionEvent e) {
int x = panel.getX();
int y = panel.getY();
if(direction == TDirection.left) {
if(x>0)
x = x - 3;
} else {
int width = getWidth();
int a = width - panel.getWidth();
if(x
==== X-dik példa ====
import javax.swing.JFrame;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
class Program02 extends JFrame {
Program02() {
setFocusable(true);
addKeyListener(new TAdapter());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
public static void main(String args[]) {
new Program02();
}
public static void balra() {
System.out.println("balra");
}
class TAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if (keycode == 'p' || keycode == 'P') {
System.out.println("Kis p vagy nagy P");
}
switch (keycode) {
case KeyEvent.VK_LEFT:
balra();
break;
case KeyEvent.VK_RIGHT:
System.out.println("jobbra");
break;
case KeyEvent.VK_DOWN:
System.out.println("le");
break;
case KeyEvent.VK_UP:
System.out.println("fel");
break;
case KeyEvent.VK_SPACE:
System.out.println("Szóköz");
break;
case KeyEvent.VK_A :
System.out.println("a");
break;
}
}
}
}
==== Karakter lekérdezése ====
public void keyTyped(KeyEvent event) {
System.out.println(event.getKeyChar());
}
===== Húzás =====
A MouseMotionAdapter lehetővé teszi egy komponens húzását.
A következő példában egy szöveget húzgálhatunk az ablakon.
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseEvent;
import java.awt.Component;
public class Program01 extends JFrame {
JPanel panel = new JPanel();
JLabel cimke = new JLabel();
Program01() {
cimke.setText("Jóska");
cimke.setLocation(100, 10);
cimke.setSize(50, 15);
cimke.addMouseMotionListener(new Cimke_Dragged());
panel.add(cimke);
add(panel);
panel.setLayout(null);
setSize(400, 300);
setVisible(true);
}
public void rePaint() {
repaint();
}
class Cimke_Dragged extends MouseMotionAdapter {
public void mouseDragged(MouseEvent e) {
Component c = e.getComponent();
c.setLocation( c.getX()+e.getX(), c.getY()+e.getY());
rePaint();
}
}
public static void main(String args[]) {
new Program01();
}
}
===== ActionCommand =====
Az akcióparancsok az események kezelésének egy újabb módja.
A következő példában az ActionListener interfész mellett
használjuk az akcióparancsot.
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.FlowLayout;
class Program01 extends JFrame implements ActionListener {
JButton okButton = new JButton("Ok");
JButton cancelButton = new JButton("Mégsem");
String OK_COMMAND = "ok";
String CANCEL_COMMAND = "cancel";
Program01() {
okButton.addActionListener(this);
okButton.setActionCommand(OK_COMMAND);
cancelButton.addActionListener(this);
cancelButton.setActionCommand(CANCEL_COMMAND);
add(okButton);
add(cancelButton);
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
public static void main(String args[]) {
new Program01();
}
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals(OK_COMMAND)){
setTitle("Ok");
}else if(e.getActionCommand().equals(CANCEL_COMMAND)){
setTitle("Nem jó");
}
}
}
===== Ablakesemények kezelése =====
A grafikus felületen megjelenő ablakok az operációs rendszer
alapértelmezett akcióit váltják ki az egyes eseményekre.
Ha szeretnénk ebbe beleszólni, akkor a WindowListenerre
van szükségünk.
import javax.swing.JFrame;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
class Program01 extends JFrame {
Program01() {
addWindowListener(new WindowListener(){
public void windowDeactivated(WindowEvent event) {}
public void windowActivated(WindowEvent event) {}
public void windowDeiconified(WindowEvent event) {}
public void windowIconified(WindowEvent event) {}
public void windowClosed(WindowEvent event) {}
public void windowClosing(WindowEvent event) {}
public void windowOpened(WindowEvent event) {}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
centerWindow(this);
setVisible(true);
}
public static void centerWindow(java.awt.Window frame) {
java.awt.Dimension dimension =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
public static void main(String[] args) {
new Program01();
}
}
A példában persze egyik metódus sincs megvalósítva. Válasszuk ki
a kívánt eseményt és a {} között írjuk meg a metódus törzsét.
Például:
public void windowClosing(WindowEvent event) {
System.exit(0);
}
===== Action =====
Eseménykezelés az Action és AbstractAction osztályokkal.
import javax.swing.JFrame;
import javax.swing.Action;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
class Program01 extends JFrame {
Action leftAction = new LeftAction("Felirat");
JButton btnTest = new JButton(leftAction);
Program01() {
add(btnTest);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
centerWindow(this);
setVisible(true);
}
public static void centerWindow(java.awt.Window frame) {
java.awt.Dimension dimension =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = (int)((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int)((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
public static void main(String[]args) {
new Program01();
}
class LeftAction extends AbstractAction {
public LeftAction(String text) {
super(text);
}
public void actionPerformed(ActionEvent e) {
setTitle("vmi");
}
}
}
===== Gombok tömbben =====
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class Gombok extends JFrame implements ActionListener {
JButton[] gombok = new JButton[64];
GridLayout gridLayout = new GridLayout(8, 8);
public Gombok() {
Integer i = 0;
for(JButton gomb : gombok) {
gomb = new JButton();
gomb.addActionListener(this);
i++;
gomb.setActionCommand(i.toString());
add(gomb);
}
setLayout(gridLayout);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
String cmd = event.getActionCommand();
System.out.println(cmd);
switch(cmd) {
case "1" :
System.out.println("első");
break;
case "2" :
System.out.println("második");
break;
default:
System.out.println("más");
}
}
public static void main(String[] args) {
new Gombok();
}
}
===== Külső Linkek =====
* http://docs.oracle.com/javase/tutorial/uiswing/events/index.html
* http://docstore.mik.ua/orelly/java-ent/jfc/ch02_06.htm
* http://www.wilsonmar.com/1javaawt.htm
* http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html
* http://zetcode.com/tutorials/javaswingtutorial/draganddrop/
* http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html