Table of Contents

Events και Event Listeners

Όταν ο χρήστης πατήσει ένα πλήκτρο από το πληκτρολόγιο ή μετακινήσει το ποντίκι, ο window manager στέλνει μία ειδοποίηση (event) που σηματοδοτεί την ενέργεια που έκανε ο χρήστης. Για παράδειγμα, πατώντας με τη βοήεια του ποντικιού (αριστερό click) ένα κουμπί από το γραφικό περιβάλλον, μετακινώντας το ποντίκι πάνω στο ενεργό παράθυρο ή εισάγοντας ένα χαρακτήρα από το πληκτρολόγιο παράγεται ένα event που σηματοδοτεί την αλλαγή που έκανε ο χρήστης.

Ο window manager δημιουργεί events για κάθε απειροελάχιστη μεταβολή της θέσης του ποντικιού ή για το πάτημα ενός κουμπιού από το πληκτρολόγιο. Τα περισσότερα προγράμματα δεν τα ενδιαφέρει το σύνολο των events που παράγονται. Προκειμένου ένα πρόγραμμα να μην “βομβαρδίζεται” με πολλά διαφορετικά events τα οποία του είναι αδιάφορα θα πρέπει να θεσπίσει του δικούς του κανόνες για το ποια events το ενδιαφέρουν. Η θέσπιση των κανόνων αυτών γίνεται μέσα από αντικείμενα τύπου event listeners, τα οποία ακούν σε συγκεκριμένου τύπου events.

Θα πρέπει να τονίσουμε ότι υπάρχουν διαφορετικοί τύποι event για κάθε διαφορετικό τύπο αλληλεπίδρασης του χρήστη με το γραφικό περιβάλλον. Για παράδειγμα, η μετακίνηση του ποντικιού ή το πάτημα ενός κουμπιού από το ποντίκι παράγει ένα MouseEvent ενώ το πάτημα ενός κουμπιού ή η επιλογή ενός menu παράγει ένα ActionEvent. Επομένως, το κάθε πρόγραμμα θα πρέπει να θεσπίσει τους κατάλληλους event listeners που διαχειρίζονται τα event που παράγονται από τις οντότητες του γραφικού περιβάλλοντος που ενδιαφέρουν. Η διαδικασία διαχείρισης και αντίδρασης του προγράμματος σε ένα event, ονομάζεται event handling.

Η εικόνα που ακολουθεί συνοψίζει την διαδικασία για την εφαρμογή της προηγούμενης ενότητας που περιέχει μόνο ένα κουμπί (button).

Οι βασικοί τύποι των διαφορετικών Event

Τα περισσότερα από τα events που μας ενδιαφέρουν κληρονομούν την κλάση java.awt.AWTEvent που με τη σειρά της κληρονομεί την κλάση java.util.EventObject. Οι κλάσεις των events βρίσκονται μέσα στα πακέτα java.awt.event και javax.swing.event. Οι βασικοί τύποι event είναι οι εξής:

Event Listeners

Για τον πιάσιμο των παραπάνω τύπων events, η Java ορίζει ένα σύνολο από interfaces, τα οποία τα οποία όταν υλοποιούνται από μία κλάση και συνδυαστούν με κάποιο από τα components του γραφικού περιβάλλοντος έχουν την δυνατότητα να πιάσουν συγκεκριμένους τύπους από events. Όλα τα interfaces που μας ενδιαφέρουν είναι απόγονοι της κλάσης java.util.EventListener και βρίσκονται στο πακέτο java.awt.event

Οι κυριότεροι Event Listeners είναι οι εξής:

Παράδειγμα - Πιάνοντας ένα event μέσω ενός Event Listener

Παρακάτω δίνεται το παράδειγμα της κλάσης EventHandling, η οποία δημιουργεί ένα παράθυρο και “πιάνει” διάφορα events που παράγονται από το ποντίκι και το πληκτρολόγιο στα επιμέρους components της παραθυρικής εφαρμογής. Η εφαρμογή δημιουργεί ένα κουμπί και τα εξής τέσσερα (3) textfield πεδία:

Το κουμπί εμφανίζει διαφορετικά μηνύματα όταν ο δρομέας του ποντικιού βρίσκεται πάνω από αυτό, απομακρύνεται ή γίνεται click.

EventHandling.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
 
public class EventHandling extends JFrame {
  JFrame frame;
  JPanel framePanel;
  JPanel textFieldPanel;
  JButton button;
  JTextField actionEventTextField;
  JTextField keyEventTextField;
  JTextField mouseMotionEventTextField;
  int buttonClickedCount;
  private static int TEXT_FIELD_SIZE = 20;
 
  public EventHandling() {    
    frame = new JFrame("CE325 - Event Handling Demo");    
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
    button = new JButton("  Put Cursor!  ");
    button.setBackground(new Color(0xe9,0xe9,0xe9));
    button.setFont(new Font("Courier", Font.BOLD, 15));
    Border buttonBorder = BorderFactory.createRaisedBevelBorder();
    button.setBorder(buttonBorder);
 
    buttonClickedCount = 0;
    button.addActionListener( new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonClickedCount++;
        actionEventTextField.setText("Button clicked "+buttonClickedCount+" times!");
      }
    });
 
    button.addMouseListener( new MouseListener() {
      public void mouseClicked(MouseEvent e) {        
      }
      public void mouseEntered(MouseEvent e) {
        button.setText("  Press  me!   ");
      }
      public void mouseExited(MouseEvent e) {
        button.setText("  Put Cursor!  ");
      }
      public void mousePressed(MouseEvent e) {
        button.setText("  Release Me!  ");
      }
      public void mouseReleased(MouseEvent e) {
        button.setText("  Press again  ");
      }
    });
 
    frame.add(button, BorderLayout.EAST);
 
    textFieldPanel = new JPanel(new GridLayout(5, 2, 3, 3));    
 
    textFieldPanel.add(new JLabel("Button Clicks:"));
    actionEventTextField = new JTextField("", TEXT_FIELD_SIZE);    
    textFieldPanel.add(actionEventTextField);
 
    textFieldPanel.add(new JLabel("Keyboard Input:"));
    keyEventTextField = new JTextField("", TEXT_FIELD_SIZE);
    keyEventTextField.addKeyListener( new KeyListener() {
      public void keyTyped(KeyEvent e) {        
        keyEventTextField.setText("Character \""+e.getKeyChar()+"\" was pressed");
      }
      public void keyPressed(KeyEvent e) {
        keyEventTextField.setText("");
      }
      public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_SHIFT || 
           e.getKeyCode() == KeyEvent.VK_CONTROL ||
           e.getKeyCode() == KeyEvent.VK_ENTER
           )
          return;        
        String str = keyEventTextField.getText();        
        str = str.substring(0,str.length()-1);
        keyEventTextField.setText(str);
      }
    });    
    textFieldPanel.add(keyEventTextField);    
 
    textFieldPanel.add(new JLabel("Mouse current position on window:"));
    mouseMotionEventTextField = new JTextField("", TEXT_FIELD_SIZE);
    frame.addMouseMotionListener( new MouseMotionListener() {
      public void mouseDragged(MouseEvent e) {
      }
      public void mouseMoved(MouseEvent e) {
        mouseMotionEventTextField.setText("Cursor position at "+e.getX()+", "+e.getY());
      }
    });    
    textFieldPanel.add(mouseMotionEventTextField);    
 
    frame.add(textFieldPanel, BorderLayout.CENTER);
 
    frame.pack();
    frame.setVisible(true);
  }
 
  public static void main(String []args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
       new EventHandling();
      }
    });
  }
}