19.7 JButton lernt dazu
 
Erben Im Sinne der Modularisierung und der inneren Logik einer objektorientierten Sprache ist die RechnerGUI nicht zufrieden stellend. Warum soll in der GUI abgefragt werden, welches Button ein Ereignis meldet und die Ereignisse dann Button-spezifisch behandelt werden? Nahe liegender wäre es doch, wenn das Button selbst 'sein' Ereignis behandelt, und es müsste doch selbst wissen, wann es gedrückt wurde. Ein JButton-Objekt, wie es von Java angelegt ist, kann das aber nicht. Wir müssen ein 'intelligentes' Button, das das kann, was wir uns wünschen, selbst implementieren, was übrigens viel leichter ist als man zunächst annimmt. Wir nützen nämlich aus, dass Java erlaubt, fertige Klassen zu beerben. Gehen wir Schritt für Schritt vor, um zu lernen, wie man eine Klasse von einer anderen erben lassen kann.

Nennen wir unsere neue Button-Klasse JButtonQuadGl um auszudrücken, dass sie alle Eigenschaften hat, die auch die Klasse JButton hat, aber zusätzlich auf das Anklicken eines eines seiner Instanzen die Werte a, b und c aus den Eingabefenstern  der GUI liest und die Lösung der Quadratischen Gleichung
ax2 + bx + c = 0  im Ausgabefenster der GUI ausgibt.
 

Kopf der neuen Klasse public class JButtonQuadGL extends JButton {
  ...
}

Mit dem reservierten Wort extends gefolgt vom Namen der Klasse JButton, teilen wir dem Kompiler mit, dass JButtonQuadGl JButton beerbt. Alle Attribute und alle Methoden der Klasse JButton sind nun auch Attribute bzw. Methoden der Klasse JButtonQaudGL, so, als wären sie hier implementiert.
Kommen wir zu den zusätzlichen Eigenschaften unseres neuen Buttons. Es soll selbst auf das Ereignis, nämlich 'gedrückt' zu werden, reagieren können. Es soll also satt der GUI selbst die Methode
actionPerformed(ActionEvent e) implementieren. Erinnern wir uns, das geht nur, wenn unsere Klasse das Interface ActionListener implementiert. Wie korrigieren also unseren Kopf zu:
 

der neue Kopf public class JButtonQuadGL extends JButton
                           implements ActionListener{
  ...
  public void actionPerformed(ActionEvent e){
    ...
  }
}
 

Schauen wir uns zunächst den gesamten Quelltext an und kommentieren danach einzelne wichtige Stellen.

 

Klasse JButtonQuadGL

Download:
JButton QuadGL. java

import javax.swing.*;
import java.awt.event.*;

public class JButtonQuadGl extends JButton 
                           implements ActionListener{

  RechnerGUI rechner;

  public JButtonQuadGl(String beschriftung, RechnerGUI rechner){
   super (beschriftung);
   this.rechner = rechner;
  }
  public void actionPerformed(ActionEvent e){
   double a=Double.parseDouble(rechner.eingabeFeldA.getText());
   double b=Double.parseDouble(rechner.eingabeFeldB.getText());
   double c=Double.parseDouble(rechner.eingabeFeldC.getText());
   rechner.ausgabeFeld.setText(Mathematik.loeseQuadGl(a,b,c));
  }
}
Kommentare Unser JButtonQuadGL-Objekt muss das RechnerGUI-Objekt kennen, damit er dessen Eingabefelder auslesen und in sein Ausgabefeld schreiben kann. Wir deklarieren deshalb einen rechner als RechnerGUI-Objekt.

RechnerGUI rechner;

Damit ist die Verbindung noch nicht geknüpft, das geschieht, wie wir gleich noch sehen werden im Konstruktor:

public JButtonQuadGl(String beschriftung, RechnerGUI rechner){
  super (beschriftung);
  this.rechner = rechner;
} 

Die Parameterliste des Konstruktors enthält zwei Parameter. Zunächst einen, in dem wir die Beschriftung unsers Buttons übergeben und zweitens den GUI-Rechner. Beim letzten wird also die Verknüpfung mit der RechnerGUI geschaffen.
Mit
super(...) rufen wir einen Konstruktor der Klasse auf, von der JButtonQuadGL erbt, also aus der Klasse JButton. Da JButton mehrere Konstruktoren besitzt, entscheidet die Signatur, welcher gemeint ist. In unserem Beispiel ist es JButton(String name), also der, bei dem man den Button zusätzlich beschriften kann. Wir sagen hier 'zusätzlich', weil der Konstruktor außer dem Setzten der Beschriftung noch jede Menge anderer Dinge tut. Schließlich wird mit  this.rechner = rechner; die Referenz des übergebenen GUIRechners, also rechner auf den in unserer neune Klasse bereits deklarierten, gesetzt. Damit steht der übergebene Rechner nicht nur im Konstruktor sondern auch in der ganzen Klasse zur Verfügung. Das ist wichtig, da wir die Methoden des rechners (Auslesen aus den Eingabefeldern und Schreiben in das Ausgabefeld) in der Methode actionPerformed(ActionEvent e) gebraucht werden.

Wir kommen jetzt zur Methode actionPerformed(ActionEvent e). Sie sieht der schon von der alten rechnerGUI-Klasse bekannten ziemlich ähnlich. Der Wert für a wird aus dem Textfeld eingabeFeldA des übergeben Objektes rechner gelesen: Statt eingabeFeldA.getText(); schreiben wir jetzt: rechner.eingabeFeldA.getText();. Die bei diesem Aufruf gelieferte Zeichenkette wird der Double-Klassenmethode parseDouble(String name) übergeben, die, falls die Eingabe sinnvoll war, einen Double-Wert liefert, der schließlich in a abgelegt wird.
 

Die neue rechnerGUI
(mit nur einem Button)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
  *
  * <Beschreibung>
  *
  * @version 1.0 vom 26.05.2003
  * @author Michael Pohlig
  */
public class RechnerGUI extends JFrame  {
  // Anfang Variablen
  JPanel centerPanel, nordPanel;
  JLabel aLabel, bLabel, cLabel;
  JButtonQuadGl qglButton;
  JTextField eingabeFeldA, eingabeFeldB, eingabeFeldC, ausgabeFeld;
  // Ende Variablen

  public RechnerGUI (String title) {
    // Frame-Initialisierung
    super (title);
    addWindowListener(new WindowAdapter() {
      public void windowClosing (WindowEvent evt) {System.exit(0);}});
    setSize(400, 200);
    setLocation(50,50);
    Container cp = getContentPane();
    cp.setLayout(new BorderLayout());
    
    nordPanel = new JPanel(new GridLayout());
    cp.add(nordPanel,BorderLayout.NORTH);

    centerPanel = new JPanel(new GridLayout(3,2,30,10));
    cp.add(centerPanel,BorderLayout.CENTER);
    

    // Anfang Komponenten
    
    aLabel = new JLabel("a:   ");
    aLabel.setHorizontalAlignment(aLabel.RIGHT);
    nordPanel.add(aLabel);

    eingabeFeldA = new JTextField("0");
    eingabeFeldA.setHorizontalAlignment(eingabeFeldA.RIGHT);
    nordPanel.add(eingabeFeldA);

    bLabel = new JLabel("b:   ");
    bLabel.setHorizontalAlignment(bLabel.RIGHT);
    nordPanel.add(bLabel);

    eingabeFeldB = new JTextField("0");
    eingabeFeldB.setHorizontalAlignment(eingabeFeldB.RIGHT);
    nordPanel.add(eingabeFeldB);
    
    cLabel = new JLabel("c:    ");
    cLabel.setHorizontalAlignment(cLabel.RIGHT);
    nordPanel.add(cLabel);

    eingabeFeldC = new JTextField("0");
    eingabeFeldC.setHorizontalAlignment(eingabeFeldB.RIGHT);
    nordPanel.add(eingabeFeldC);

    
    qglButton = new JButtonQuadGl("Löse ax^2 + bx + c = 0",this);
    centerPanel.add(qglButton);                                  
    qglButton.addActionListener(qglButton);                      
    
    ausgabeFeld = new JTextField();
    ausgabeFeld.setHorizontalAlignment(ausgabeFeld.RIGHT);
    cp.add(ausgabeFeld,BorderLayout.SOUTH);
    ausgabeFeld.setEditable(false);
    
    // Ende Komponenten

    setVisible(true);
  }

          
          
  public static void main (String[] args) {
    new RechnerGUI("Rechner");
  }
}
Erstes
Merkmal:
Die Klasse rechnerGUI implementiert nicht mehr das Interface ActionListener; das macht jetzt der neue Button. Somit entfällt auch die Implementierung der Methode actionPerformed(ActionEvent e).
 
Zweites Merkmal: Die Deklaration ist angepasst.

 
Drittes Merkmal: Beim Aufruf des Konstruktor

JButtonQuaGL(String name, rechnerGUI rechner)


für die Erzeugung des
JButtonQuadGL-Objekts wird, wie schon oben erwähnt, zuerst die Beschriftung für den Button und an zweiter Stelle das rechnerGUI-Objekt, das die Eingabe- und Ausgabefelder hat, übergeben. Diese Object ist aber das aufrufende Objekt, weshalb wir this übergeben.

In

qglButton.addActionListener(qglButton);

wird der qglButton beim ActionListener angemeldet und als Paramter das Objekt übergeben, das auf das Ereignis reagieren soll, das ist in unserem Fall wieder qglButton.

 

zu 19.8 Klassenhierarchie des neuen Rechners
zur Startseite www.pohlig.de  (C) MPohlig 2003