8.2 GUI für die Fachklasse Mathematik

 
Ein wichtiges Paradigma in der heutigen Programmierung ist dies: Trenne stets Fachklasse von der grafischen Bedieneroberfläche (engl. Grafical User Interface = GUI). Nachdem wir in der Klassen Mathematik (vgl. dazu Kapitel 7) einen typische Vertreterin einer Fachklasse kennen gelernt haben und nachdem wir zuletzt gesehen haben, wie wir eine grafische Oberfläche programmieren können, können wir uns daran machen, eine GUI für die Fachklasse Mathematik zu implementieren. Quasi nebenbei werden wir dabei lernen, wie man diverse Layouts kombiniert, um ganz bestimmte Anordnungen von grafischen Objekten auf der Oberfläche zu erreichen. Anschließen werden sich kleine Kapitel, in denen beschrieben wird, wie man, ist eine GUI einmal geschrieben, mit minimalem Aufwand zu jar-Dateien und Applets dieser GUI erzeugt.
 
8.2.1 JFrame-Variante
 
Borderlayout Das Bordelayout teilt den Behälter für grafische Objekte wie Buttons etc. in 5 Bereiche: North, South, West, East und Center. Wie diese angeordnet sind, zeigt das nebenstehende Bild.  Wollen wir ein Objekt z.B. ein JButton-Objekt mit dem Namen buttonGgT etwa in den Bereich East  des Behälters cp ablegen, so geschieht dies durch:

cp.add(buttonGgT, BorderLayout.EAST);

zuvor muss der Behälter cp ein Borderlayout bekommen:

cp.setLayout(new BorderLayout());

Wir erkennen, man muss für den Behälter die Methode setLayout(...) aufrufen. Diese Methode erwartet, dass man das Layout spezifiert, was durch die Übergabe eines Layout-Objektes, hier eines BorderLayout-Objektes geschieht. Da dieses noch nicht existiert, wird es mit new erzeugt (es ist ein anonymes Objekt, da es keiner eigenen Variablen zugewiesen ist).
 

Gridlayout Wird ein Behälter mit einem Gridlayout versehen, dann wird er in Bereiche aufgeteilt, die wie die Zellen einer Tabelle angeordnet sind. Mit

cp.setLayout(new GridLayout(3,2));

wird ein Bereich von drei Zeilen und 2 Spalten erzeugt. Die Bereiche sind dabei alle gleich groß. Die Objekte, die man in den Zellen ablegt, passen sich den Zellengrößen an und stoßen 'hart' aufeinander. Will man dies vermeiden, möchte man also, dass die abgelegten Objekte etwas von einander getrennt sind, benutz man einen anderen Konstruktor für das Gridlayout.

cp.setLayout(new GridLayout(3,2,1,4));

Dabei definiert die 1 den horizontalen und die 4 den vertikalen Abstand der Zellen. Benutz man für das Grindlyout den Standardkonstruktor,

cp.setLayout(new GridLayout());

so wird eine Zeile erzeugt und die Anzahl der Spalten richtet sich nach der Anzahl der Objekte, die man in dem Behälter ablegt.
 

Das Layout der Rechner-GUI Betrachten wir das gewünschte Layout unserer Rechner-GUI. Wir können sie durch Kombinationen von Border- und Gridlayouts erzeugen.
 

  Beginne wir mit dem Bereich der Buttons. Es ist leicht nachzuvollziehen, dass man den Behälter mit einem Borderlayout versieht, auf die Belegung von den Bereichen East und West verzichtet, und den Center-Bereich selbst mit einem Gridlayout mit 2 Zeilen und 3 Spalten versieht.

Wir deklarieren unseren Behälter cp, einen Zeichenbereich Panel für das Zentrum, das wir deshalb centerPanel nennen und vom Typ JPanel ist.
 

  private JPanel centerPanel;


//Konstruktor
Container cp = getContentPane();
cp.setLayout(new BorderLayout());

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

 
  Wir erzeugen ein JPanel-Objekt, versehen es dabei gleich mit dem gewünschten Gridlayout.
 
  Ebenfalls leicht nach zu vollziehen ist, dass wir im 'Norden' des Behälters ein Gridlayout mit einer Zeile erzeugen. Die Spalten richten sich nach den Objekten, die wir ablegen, in unserem Beispiel sind es 6. Der Süden bekommt nur ein Objekt, benötigt also keine weitere Unterstruktur.
 
Die Objekte Wenden wir uns den Objekten zu, die wir in unserem 'Setzkasten' unterbringen wollen. Neben den JButton-Objekte, sind dies JLabel- und JTextfield-Objekte.

Labels sind durchsichtige Bereiche, in die man etwas hineinschreiben kann. Mit

labelA = new JLabel("a: ");

wird ein
JLabel-Objekt erzeugt, das den Schriftzug "a: " enthält. Das Objekt wird der bereits deklarierten Variablen labelA zugewiesen.

Damit der Schriftzug rechtsbündig erscheint, verwenden wir die MethodesetHorizontalAlignment(..):

labelA.setHorizontalAlignment(SwingConstants.RIGHT);

und fügen das Objekt schließlich dem Nordpanel zu:

northPanel.add(labelA);

Hinter dem Label legen wir ein Textfeld ab, in das der Programmbenutzer Daten ablegen kann, die das Programm selbst abfragen kann:

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

  Damit stehen alle Komponenten des Programms  zur Verfügung:
 
 
  private JPanel northPanel, centerPanel;
  private JLabel labelA, labelB, labelC;
  private JTextField eingabeFeldA, eingabeFeldB, 
                     eingabeFeldC, ausgabefeld;
  private JButton buttonFakultaet, buttonggT, 
                  buttonkgV, buttonFib, 
                  buttonQuadGl, buttonGl;
  

  public RechnerGUI(String title) {
    super(title);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(450, 150);
    Container cp = getContentPane();
    cp.setLayout(new BorderLayout());

    // Anfang Komponenten
    northPanel = new JPanel(new GridLayout());
    cp.add(northPanel, BorderLayout.NORTH);

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

    labelA = new JLabel("a:    ");
    labelA.setHorizontalAlignment(SwingConstants.RIGHT);
    northPanel.add(labelA);

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

    labelB = new JLabel("b:    ");
    labelB.setHorizontalAlignment(SwingConstants.RIGHT);
    northPanel.add(labelB);

    eingabeFeldB = new JTextField("0");
    eingabeFeldB.setHorizontalAlignment(SwingConstants.RIGHT);
    northPanel.add (eingabeFeldB);

    labelC = new JLabel("c:    ");
    labelC.setHorizontalAlignment(SwingConstants.RIGHT);
    northPanel.add(labelC);

    eingabeFeldC = new JTextField("0");
    eingabeFeldC.setHorizontalAlignment(SwingConstants.RIGHT);
    northPanel.add (eingabeFeldC);


    buttonggT = new JButton("ggT(a,b)");
    centerPanel.add (buttonggT);
    buttonggT.setHorizontalAlignment(SwingConstants.CENTER);
    buttonggT.addActionListener(this);

    buttonkgV = new JButton("kgV(a,b)");
    centerPanel.add (buttonkgV);
    buttonkgV.setHorizontalAlignment(SwingConstants.CENTER);
    buttonkgV.addActionListener(this);

    buttonFakultaet = new JButton("a!");
    centerPanel.add (buttonFakultaet);
    buttonFakultaet.setHorizontalAlignment(SwingConstants.CENTER);
    buttonFakultaet.addActionListener(this);

    buttonQuadGl = new JButton("Löse ax²+bx+c = 0");
    centerPanel.add (buttonQuadGl);
    buttonQuadGl.setHorizontalAlignment(SwingConstants.CENTER);
    buttonQuadGl.addActionListener(this);

    buttonGl = new JButton("Löse ax+b = 0");
    centerPanel.add (buttonGl);
    buttonGl.setHorizontalAlignment(SwingConstants.CENTER);
    buttonGl.addActionListener(this);

    buttonFib = new JButton("Fibonacci(a)");
    centerPanel.add (buttonFib);
    buttonFib.setHorizontalAlignment(SwingConstants.CENTER);
    buttonFib.addActionListener(this);

    ausgabefeld = new JTextField("");
    ausgabefeld.setHorizontalAlignment(SwingConstants.RIGHT);
    cp.add (ausgabefeld, BorderLayout.SOUTH);

    // Ende Komponenten

    setVisible(true);
  }
Ereignis-
behandlung
Bleibt noch die Implementierung der Methode actionPerformed(..).  Mit ihr beschäftigen wir uns jetzt. Dabei lernen wir auch, wie man Textfelder ausliest bzw. beschreibt.

int
eingabeA = Integer.parseInt(eingabeFeldA.getText());
int eingabeB = Integer.parseInt(eingabeFeldB.getText());
int eingabeC = Integer.parseInt(eingabeFeldC.getText());

 
  Mit eingabeFeldA.getText()liest man den Inhalt des Textfeldes eingabeA. Dabei liefert die Methode ein String-Objekt, dessen Inhalt wir aber als Integer-Zahl verwenden wollen, dies geschieht mit der Integer-Klassen-Methode: parseInt(String text). Anstelle von

int eingabeA = Integer.parseInt(eingabeFeldA.getText());

hätten wir verständlicher, dafür aber umständlicher schreiben können.

String eingabeAText = eingabeFeldA.getText();
int eingabeA = Integer.parseInt(eingabeAText);

 

  Wir bestimmen das Objekt, das das Ereignis ausgelöst hat:
 
 
Object obj=e.getSource();
 
if (obj==buttonggT){
  ausgabefeld.setText(""+ Mathematik.ggT(eingabeA, eingabeB));
}
  Mathematik.ggT(eingabeA, eingabeB); berechnet den ggT der beiden Zahlen, mit

""+ Mathematik.ggT(eingabeA, eingabeB),

also mit der Konkatenation mit einem Leerstring wird das Ergebnis der Berechnung zu einem String, den wir mit der Methode setText(String text) in das Ausgabefeld schreiben.
 

Besonderheit Die Methoden bigFakutaet(..) und bigFibn(..) erwarten keinen Parameter vom Typ int, sondern ein Objekt der Klasse BigInteger. Wir lesen also das entsprechende Textfeld aus, erzeugen daraus ein BigInteger-Objekt, das wir direkt der Methode, hier bigFakultaet(..), übergeben.
 
Download:
Rechner-
GUI.java

Mathematik.
java
ausgabefeld.setText(""+Mathematik.bigFakultaet(
  new java.math.BigInteger(eingabeFeldA.getText())));

Vergleiche dazu auch die Aufgabe 1 in 8.2.2 Übungen.
   
zu 8.2.2 Übungen
8.2.3 JFrame-Variante als jar-Datei
zur Startseite www.pohlig.de  (C) MPohlig 2006