Tartalomjegyzék
Java eseménykezelés
- Szerző: Sallai András
- Copyright © 2011, Sallai András
- Szerkesztve: 2011, 2013, 2014, 2015, 2019
- Licenc: 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.
- Esemeny.java
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.
- Program.java
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:
- Program.java
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.
- Program01.java
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):
- Program01.java
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<a) x = x + 3; } panel.setLocation(new Point(x, y)); } private void OnKeyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER) { timer.start(); } if(e.getKeyCode() == KeyEvent.VK_RIGHT) { direction = TDirection.right; } if(e.getKeyCode() == KeyEvent.VK_LEFT) { direction = TDirection.left; } } public static void main(String args[]) { new Program01(); } }
X-dik példa
- Program01.java
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
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.
- Program01.java
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.
- Program01.java
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.
- Program01.java
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.
- Program01.java
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
- Gombok.java
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(); } }