Weitere aktuelle Java-Titel finden Sie bei dpunkt.
 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index


9.3.3

Ein Beispiel: Erzeugen grafischer Buttons


Grafische Buttons können sowohl Applets als auch Applikationen auflockern. Man kann durch ein Bild die Aktion kenntlich machen, die durch Drücken des Buttons ausgelöst wird. Das ist von Vorteil, wenn alle Buttons die gleiche Größe besitzen müssen oder wenn es schwierig ist, eine kurze Formulierung der Aktion für das Label des Buttons zu finden. Buttons, die diese Funktionalität besitzen, sind bereits in Swing enthalten. Dennoch soll in diesem Abschnitt gezeigt werden, wie man mit den Standard-AWT-Komponenten solche Buttons realisieren kann. Hierbei steht nicht die Komponente an sich, sondern vielmehr die Vorgehensweise bei der Ereignisbehandlung im Vordergrund.

Bei der Implementierung von grafischen Buttons muss man eine Vielzahl von Ereignissen berücksichtigen: Die Reaktion auf diese Ereignisse muss durch eine geeignete Implementierung der Event-Handling-Methoden erfolgen. Auf dem Button soll ein Bild dargestellt werden. Die Größe des Buttons ist von der Größe des Bildes abhängig. Ansonsten soll er dieselbe Funktionalität wie ein normaler Button besitzen. Erhält er den Fokus, so wird er schwarz umrahmt, wird er gedrückt, so wird er »gedrückt« gezeichnet, d.h., auf dem Bildschirm entsteht ein entsprechendes räumliches Bild des Knopfs.

Das Event-Handling wird an diesem Beispiel Schritt für Schritt durchgesprochen. Die Klasse GraphicButton, die implementiert werden soll, besitzt vier boolesche Variablen, die den aktuellen Status des Buttons widerspiegeln: Je nach den Werten dieser Variablen wird der Button »gedrückt« oder »nicht gedrückt« gezeichnet. Der Button wird »gedrückt« gezeichnet, wenn sich der Mauszeiger gerade auf dem Button befindet und gleichzeitig eine Maustaste gedrückt ist oder wenn keyaction den Wert true hat. Zunächst erfolgt die Implementierung der Fokus-Events. Die Reaktion auf die Fokus-Events wird in der Methode processFocusEvent(FocusEvent) vorgenommen. Wenn der Button gedrückt werden soll, muss er zuerst einmal den Fokus erhalten. Ist dies erfolgt, wird ein Fokus-Event mit der ID FOCUS_GAINED erzeugt. In diesem Fall wird focused auf true gesetzt. Analog dazu wird focused auf false gesetzt, wenn ein Fokus-Event mit der ID FOCUS_LOST erzeugt wird. Der Button erhält einen Rahmen, sobald er den Fokus besitzt:
  public void processFocusEvent(FocusEvent e) {
    switch(e.getID()) {
    case FocusEvent.FOCUS_GAINED:
      focused = true;
      break;
    case FocusEvent.FOCUS_LOST:
      focused = false;   // Button verliert Fokus
      keyaction = false; // Tastendruck wird ungültig
    }
    repaint();         // Button neu zeichnen
    super.processFocusEvent(e);
  }

Bei FOCUS_LOST wird auch gleichzeitig keyaction auf false gesetzt, da der Fokus bei gedrückter Space-Taste wechseln könnte, indem man mit der Maus eine andere Komponente anwählt.

Um den Button beim Drücken auf Space »gedrückt« darzustellen, überschreibt man die Methode processKeyEvent(KeyEvent) folgendermaßen:
  public void processKeyEvent(KeyEvent e) {
    switch(e.getID()) {
    case KeyEvent.KEY_PRESSED:
      // Wurde die Leertaste gedrückt?
      if (e.getKeyCode() == KeyEvent.VK_SPACE) {
        // dann ist auch der Button gedrückt
        keyaction = true;
      }
      break;
    case KeyEvent.KEY_RELEASED:
      // Wird die Space-Taste losgelassen?
      if (e.getKeyCode() == KeyEvent.VK_SPACE) {
        // Wurde der Button durch Tastendruck gedrückt?
        if (keyaction && (actionlistener != null)) {
          // Dann erzeuge einen Action-Event
          // mit dem logischen Namen des Buttons
          actionlistener.actionPerformed(
            new ActionEvent(this,
              ActionEvent.ACTION_PERFORMED, name));
        }
        keyaction = false;    // Button ist nicht gedrückt
      }
    }
    repaint();     // neu zeichnen
    super.processKeyEvent(e);
  }

Hat das übergebene Key-Event die ID KEY_PRESSED, dann erhält keyaction den Wert true, falls die gedrückte Taste Space war (Tastencode=VK_SPACE). Anschließend wird der Button »gedrückt« gezeichnet. Die Reaktion auf ein Key-Event mit der ID KEY_RELEASED ist nicht ganz so einfach wie die eben beschriebene.

Hier wird ebenfalls zuerst überprüft, ob die losgelassene Taste die Space-Taste ist. Wenn dies zutrifft und die Space-Taste ebenfalls gedrückt wurde als der Button den Fokus hatte (keyaction ist dann true), wird ein neues ActionEvent erzeugt und an alle Komponenten geschickt, die sich als Listener registriert haben.
  actionlistener.actionPerformed(
    new ActionEvent(this,
      ActionEvent.ACTION_PERFORMED, name));
Die Verteilung an alle Listener wird von der Klasse AWTEventMulticaster übernommen.

Wird die Space-Taste wieder losgelassen, muss der Button in nicht gedrücktem Zustand erscheinen, deshalb setzt man keyaction bei einem Key-Event mit der ID KEY_RELEASED auf false.

Der nächste Schritt ist die Implementierung der Mausaktionen. Der Button kann durch die Maus nur gedrückt werden, wenn sie sich innerhalb des Buttons befindet:
  public void processMouseEvent(MouseEvent e) {
    switch(e.getID()) {
    case MouseEvent.MOUSE_ENTERED:
      mousein = true;
      break;
    case MouseEvent.MOUSE_EXITED:
      mousein = false;
      break;
    case MouseEvent.MOUSE_PRESSED:
      if (isEnabled()) {
        pressed = true;    // Button gedrückt
        requestFocus();    // Anfordern des Fokus
      }
      break;
    case MouseEvent.MOUSE_RELEASED:
      // Ist der Button gedrückt?
      if (pressed && mousein) {
        // Wenn ja, erzeuge Action-Event
        // dem mit logischem Buttonnamen
        if (actionlistener != null) {
          actionlistener.actionPerformed(
            new ActionEvent(this,
                  ActionEvent.ACTION_PERFORMED, name));
        }
      }
      pressed = false; // Button nicht mehr gedrückt
    }
    repaint();         // Button neu zeichnen
    super.processMouseEvent(e);
  }

Deshalb wird, je nachdem, ob sich die Maus in den Button oder aus ihm heraus bewegt, mousein auf true bzw. false gesetzt. Befindet sich die Maus innerhalb des Buttons, dann muss der eigentliche Mausdruck abgefragt werden. Da es nicht klar ist, ob der Button im Moment des Anklickens bereits den Fokus hat, wird dieser zuerst mit requestFocus() angefordert. pressed wird durch den Klick true. Der Button soll schließlich ein ActionEvent erzeugen, wenn die Maustaste gedrückt und wieder losgelassen wird, während sich der Mauszeiger auf dem Button befindet.

Somit hat man die volle Funktionalität implementiert, die auch ein Button besitzt, der mit der Klasse Button erzeugt wurde.

In diesem Beispiel enthält jede Methode, in der ein Ereignis abgearbeitet wird, einen Aufruf von repaint(). Dies ist erforderlich, um den Button bei einer Änderung des Status sofort neu zu zeichnen und ihn auf diese Weise zu aktualisieren.

Material zum Beispiel


 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index

Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.