4.2. GUI notikumu apstrāde

Ievads

Mērķi

  • Raksturot notikumus un notikumu apstrādi Javas tehnoloģijās
  • Rakstīt GUI notikumu apstrādes kodu
  • Aprakstīt adapterklašu jēdzienu, kā un kad tās lietot
  • Prast noteikt detalizētu lietotāja darbību, kura izraisīja notikumu, no notikuma objekta.
  • Prast atrast atbilstošu apstrādes interfeisu dažādiem notikumu tipiem
  • Izveidot piemērotas notikumu apstrādes metodes dažādiem notikumu tipiem
  • Saprast iekšējo un anonīmo klašu lietošanu notikumu apstrādē

Motivācija

  • Kas jāpievieno GUI saskarnei, lai tā kļūtu derīga?
  • Kā grafiska aplikācija apstrādā peles klikšķi vai citu lietotāja darbību?

Kas ir notikums?

  • Notikumi (event) ir objekti, kuri apraksta, kas ir noticis
  • Notikuma avots (event source) - notikuma rašanās vieta
  • Notikuma apstrādātājs (event handler) - metode, kura saņem notikuma objektu, to atšifrē un apstrādā atbilstošo lietotāja darbību
Notikuma apstrādātāja piesaiste komponentam

Delegācijas modelis

  • Notikumu var nosūtīt vairākiem notikumu apstrādātājiem
  • Notikumu apstrādātāji piereģistrējas pie komponentiem - potenciālajiem notikumu avotiem, ja tie vēlas apstrādāt šo komponentu ģenerētos notikumus
Vairāki apstrādātāji tam pašam notikumam

Delegācijas modeļa piemērs

1  import java.awt.*;
2
3  public class TestButton {
4    private Frame f;
5    private Button b;
6
7    public TestButton() {
8      f = new Frame("Test");
9      b = new Button("Press Me!");
10      b.setActionCommand("ButtonPressed");
11    }
12
13    public void launchFrame() {
14      b.addActionListener(new ButtonHandler());
15      f.add(b,BorderLayout.CENTER);
16      f.pack();
17      f.setVisible(true);
18    }
19
20    public static void main(String args[]) {
21      TestButton guiApp = new TestButton();
22      guiApp.launchFrame();
23    }
24  }
1  import java.awt.event.*;
2
3  public class ButtonHandler implements ActionListener {
4    public void actionPerformed(ActionEvent e) {
5      System.out.println("Action occurred");
6      System.out.println("Button's command is: "
7                         + e.getActionCommand());
8    }
9  }

Delegācijas modelis - uzbūve Javā

  • Klienta objekti (notikumu apstrādātāji) reģistrējas pie GUI komponenta, kuru tie vēlas novērot
  • GUI komponenti iedarbina (trigger) tikai tos apstrādātājus, kuri atbilst radušamies notikumam
  • Vairums GUI komponentu/kontroļu var izraisīt dažādus notikumu tipus
  • Šī pieeja sadala darbu starp vairākām klasēm

Notikumu kategorijas

Notikumu hierarhija

Javas GUI uzvedība

Notikumu kategorijaInterfeissMetodes
Darbība (ar pogu utml.)ActionListeneractionPerformed(ActionEvent)
Izvēle (piemēram, sarakstā)ItemListeneritemStateChanged(ItemEvent)
Peles darbībasMouseListenermousePressed(MouseEvent) mouseReleased(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mouseClicked(MouseEvent)
Peles trajektorijaMouseMotionListenermouseDragged(MouseEvent) mouseMoved(MouseEvent)
TastatūraKeyListenerkeyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent)
FokussFocusListenerfocusGained(FocusEvent) focusLost(FocusEvent)
KorekcijaAdjustmentListeneradjustmentValueChanged (AdjustmentEvent)
KomponentsComponentListenercomponentMoved(ComponentEvent) componentHidden (ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent)
LogsWindowListenerwindowClosing(WindowEvent) windowOpened(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent)
KonteinersContainerListenercomponentAdded(ContainerEvent) componentRemoved(ContainerEvent)
TekstsTextListenertextValueChanged(TextEvent)

Sarežģītāks piemērs - I

1  import java.awt.*;
2  import java.awt.event.*;
3
4  public class TwoListener
5       implements MouseMotionListener,
6                  MouseListener {
7    private Frame f;
8    private TextField tf;
9
10    public TwoListener() {
11      f = new Frame("Two listeners example");
12      tf = new TextField(30);
13    }
14
15    public void launchFrame() {
16      Label label = new Label("Click and drag the mouse");
17      // Pievieno komponentus logam
18      f.add(label, BorderLayout.NORTH);
19      f.add(tf, BorderLayout.SOUTH);
20      // Pievieno "this" objektu kā klausītāju
21      f.addMouseMotionListener(this);
22      f.addMouseListener(this);
23      // Uzstāda loga izmēru un padara to redzamu
24      f.setSize(300, 200);
25      f.setVisible(true);
26    }
27
28    // Šie ir MouseMotionListener notikumi
29    public void mouseDragged(MouseEvent e) {
30      String s =  "Peles vilkshana:  X = " + e.getX()
31                  + " Y = " + e.getY();
32      tf.setText(s);
33    }
34
35    public void mouseEntered(MouseEvent e) {
36      String s = "Pele ienaaca";
37      tf.setText(s);
38    }
39
40    public void mouseExited(MouseEvent e) {
41      String s = "Pele izgāja";
42      tf.setText(s);
43    }
44
45    // Neizmantota MouseMotionListener metode
46    // Visām klausītāja metodēm jābūt definētām 
47    // klasē, pat ja tās nelieto
48    public void mouseMoved(MouseEvent e) { }
49
50    // Neizmantotas MouseListener metodes
51    public void mousePressed(MouseEvent e) { }
52    public void mouseClicked(MouseEvent e) { }
53    public void mouseReleased(MouseEvent e) { }
54
55    public static void main(String args[]) {
56      TwoListener two = new TwoListener();
57      two.launchFrame();
58    }
59  }

Vairāki klausītāji

  • Vairāki klausītāji ļauj vairākām programmas sastāvdaļām reaģēt uz to pašu notikumu
  • Visu reģistrēto klausītāju apstrādes metodes tiek izsauktas, kad notiek notikums

Notikumu adapteri

  • Jūsu definētās klausītāju klases var mantot no "triviālajiem klausītājiem" - adapteru klasēm un pārdefinēt tikai tās metodes, kuras apstrādā mums interesantus notikumus.

Piemērs:

1  import java.awt.*;
2  import java.awt.event.*;
3
4  public class MouseClickHandler extends MouseAdapter {
5
6    // Mums vajag tikai mouseClicked() apstrādātāju,
7    // un mantošana no adaptera ļauj nerakstīt 
8    // visas citas apstrādes metodes
9
10    public void mouseClicked(MouseEvent e) {
11      // Apstrādā peles klikšķi
12    }
13  }

Iekšējas klases

1  import java.awt.*;
2  import java.awt.event.*;
3
4  public class TestInner {
5    private Frame f;
6    private TextField tf;
7
8    public TestInner() {
9      f = new Frame("Ieksheejas klases piemeers");
10      tf = new TextField(30);
11    }
12
13    public void launchFrame() {
14      Label label = new Label("Klikshkjiniet un 'velciet' peli");
15      // Pievieno komponentus logam
16      f.add(label, BorderLayout.NORTH);
17      f.add(tf, BorderLayout.SOUTH);
18      // Pievieno klausītāju, kurš lieto iekšēju klasi
19      f.addMouseMotionListener(new MyMouseMotionListener());
20      f.addMouseListener(new MouseClickHandler());
21      // Uzstaada loga izmeeru un padara to redzamu
22      f.setSize(300, 200);
23      f.setVisible(true);
24    }
25
26    class MyMouseMotionListener extends MouseMotionAdapter {
27        public void mouseDragged(MouseEvent e) {
28          String s = "Peles vilkshana:  X = "+ e.getX()
29                      + " Y = " + e.getY();
30          tf.setText(s);
31        }
32      }
33
34    public static void main(String args[]) {
35      TestInner obj = new TestInner();
36      obj.launchFrame();
37    }
38  }

Anonīmas klases

1  import java.awt.*;
2  import java.awt.event.*;
3
4  public class TestAnonymous {
5    private Frame f;
6    private TextField tf;
7
8    public TestAnonymous() {
9      f = new Frame("Anoniimas klases piemeers");
10      tf = new TextField(30);
11    }
12
13    public void launchFrame() {
14      Label label = new Label("Klikshkjiniet un 'velciet' peli");
15      // Pievieno logam komponentus
16      f.add(label, BorderLayout.NORTH);
17      f.add(tf, BorderLayout.SOUTH);
18      // Pievieno klausītāju, kurš ir anonīmā klasē
19      f.addMouseMotionListener(new MouseMotionAdapter() {
20        public void mouseDragged(MouseEvent e) {
21          String s = "Peles vilkšana:  X = "+ e.getX()
22                      + " Y = " + e.getY();
23          tf.setText(s);
24        }
25      }); // <- ievērojiet šo iekavu secību!
26      f.addMouseListener(new MouseClickHandler());
27      // Uzstāda loga izmēru un padara to redzamu
28      f.setSize(300, 200);
29      f.setVisible(true);
30    }
31
32    public static void main(String args[]) {
33      TestAnonymous obj = new TestAnonymous();
34      obj.launchFrame();
35    }
36  }

Jautājumi paškontrolei

  • Definēt notikumus un to apstrādi
  • Uzrakstīt notikumu apstrādes metodes GUI saskarnei
  • Aprakstīt adapterklašu jēdzienu, zināt kad un kā tās lietot
  • Noteikt detalizētu lietotāja darbību, kura izraisīja notikumu no notikuma objekta
  • Dažādiem notikumu tipiem atrast piemērotu klausītāja interfeisu
  • Izveidot piemērotas notikumu apstrādes metodes dažādiem notikumu tipiem
  • Saprast iekšējo un anonīmo klašu lietojumu notikumu apstrādē

Diskusiju tēma: Kādi, bez AWT pakotnē aprakstītajiem, vēl mēdz būt noderīgi GUI komponenti un to ģenerēto notikumu veidi.