17.1 Meine erste GUI

Zum Erzeugen grafischer Benutzeroberflächen verwenden wir einen GUI-Builder. GUI-Builder sind Programme, die den Entwurf grafischer Benutzeroberflächen dadurch erleichtern, dass sie es dem Entwickler ermöglichen, grafische Komponenten mit Hilfe der Maus auf einem Fenster zu platzieren und zu formatieren. Den entsprechenden Quellcode erstellt dabei der GUI-Builder.

Dennoch ist es wichtig den automatisch generierten Quellcode zu verstehen, um ihn gegebenenfalls anpassen beziehungsweise ergänzen zu können. Im diesem Abschnitt werden daher anhand eines Beispiels nicht nur die Klassen vorgestellt, die zur Erzeugung wichtiger grafischer Komponenten benötigt werden, sondern auch der hierfür notwendige Quellcode erläutert. Die Handhabung des GUI-Builders besprechen wir im Unterricht.

Beispiel

Zunächst werden wir uns mit Hilfe einer Java-Anwendung, die keinerlei fachliche Logik enthält, ansehen, aus welchen Bestandteilen eine grafische Benutzeroberfläche bestehen kann und wie eine entsprechende GUI-Klasse aufgebaut ist.

img/Abb_17_1_FensterMeineErsteGUI.jpg
Abb. 17-1: Klasse FensterMeineErsteGUI (GUI)

Fenster: JFrame

Java stellt im Packet javax.swing einige Klassen zur Verfügung, die für die Erstellung einer grafischen Benutzeroberfläche benötigt werden. Die Klasse JFrame dient dabei als Grundlage, um für eine Java-Anwendung ein Fenster zu erzeugen.

Für unser Fenster erstellen wir eine neue Unterklasse von JFrame. Hier können wir dann festlegen, wie unser Fenster aussehen soll und welche Funktionalitäten es besitzen soll.

img/Abb_17_2_JFrame.gif
Abb. 17-2: Unterklasse von JFrame
Quellcode
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
package gui;

import javax.swing.JFrame;

public class FensterMeineErsteGUI extends JFrame {

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
    }

}

Abb. 17-3: Die Klasse FensterMeineErsteGUI ist eine Unterklasse der Klasse JFrame
Erläuterungen
Zeile 8 Dem Fenster wird ein Text zugewiesen, der in der Titelleiste erscheinen soll.
Zeile 9 Wird das Fenster geschlossen, dann wird die gesamte Java-Anwendung beendet.
Zeile 10 Die Methode setBounds(x: int, y: int, width: int, height: int) legt Position und Größe des Fensters fest.
Die ersten beiden int-Werte legen die x- bzw. die y-Koordinate eines Bildschirmpunktes fest, an dem sich die linke obere Ecke des Fensters befinden soll. Der Ursprung dieses Koordinatensystems liegt dabei in der linken oberen Bildschirmecke.
Im Bespiel befindet sich die linke obere Ecke des Fensters ausgehend von der linken oberen Bildschirmecke um 100 Pixel nach rechts (x-Koordinate) und 150 Pixel nach unten (y-Koordinate) verschoben.
Der dritte int-Wert, der der setBounds-Methode übergeben wird, legt die Breite des Fensters fest und der vierte die Höhe.

Content Pane: JPanel

Die Content Pane ist eine Art Platte, die alle grafischen Komponenten, die in unserem Fenster zu sehen sein sollen, aufnimmt. Als Content Pane dient üblicherweise ein Objekt der Klasse JPanel.

Unsere von der Klasse JFrame abgeleitete Unterklasse FensterMeineErsteGUI besteht bisher lediglich aus einem Fensterrahmen. Wir müssen daher zunächst eine Art Fensterscheibe, die sogenannte Content Pane, einsetzen, auf der wir dann später weitere grafische Komponenten platzieren können. Hierfür verwendenen wir ein Objekt Klasse JPanel.

img/Abb_17_4_ContentPane.jpg
Abb. 17-4: Ein JPanel-Objekt dient als Content Pane
Quellcode-Ausschnitt
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package gui;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class FensterMeineErsteGUI extends JFrame {

    private JPanel contentPane;

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
        
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
    }

}

Abb. 17-5: Die Klasse FensterMeineErsteGUI ist eine Unterklasse der Klasse JFrame
Erläuterungen
Zeile 9 Unter der Bezeichnung contentPane wird ein Attribut vom Typ JPanel deklariert.
Zeile 16 Dem Attribut contentPane wird ein neues Objekt der Klasse JPanel zugewiesen.
Zeile 17 Es wird festgelegt, wie der Rand des JPanel-Objekts contentPane aussehen soll.
Zeile 18 Das JPanel-Objekt contentPane dient als Content Pane.
Zeile 19 Die contentPane soll keinen LayoutManager verwenden. Das bedeutet, dass grafische Komponenten, die der contentPane hinzugefügt werden, dort frei positioniert werden können.

Ein- bzw. Ausgabefeld: JTextField

Als Eingabefeld verwenden wir ein Objekt der Klasse JTextField.

In unserem Beispiel kann der Benutzer in das Eingabefeld einen Text eintragen. Dieser soll dann in der Titelleiste des Fensters erscheinen und dort den bisherigen Fenstertitel ersetzen. Hierfür benötigen wir jedoch noch die entsprechende Befehlsschaltfläche Ändern.

img/Abb_17_6_JTextField.jpg
Abb. 17-6: Ein JTextField-Objekt dient als Eingabefeld.
Quellcode-Ausschnitt
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package gui;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import java.awt.Font;

public class FensterMeineErsteGUI extends JFrame {

    private JPanel contentPane;
    private JTextField tfNeuerTitel;

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
        
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        tfNeuerTitel = new JTextField();
        tfNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNeuerTitel.setBounds(20, 46, 190, 20);
        contentPane.add(tfNeuerTitel);
    }

}

Abb. 17-7: Die Klasse FensterMeineErsteGUI
Erläuterungen
Zeile 13 Unter der Bezeichnung tfNeuerTitel wird ein Attribut vom Typ JTextField deklariert.
Zeile 25 Dem Attribut tfNeuerTitel wird ein neues Objekt der Klasse JTextField zugewiesen.
Zeile 26 Der in tfNeuerTitel angezeigte Text wird in der Schriftart Tahoma, mit dem Schriftstil Font.PLAIN2 und der Schriftgröße 12 formatiert.
Zeile 27 Position und Größe von tfNeuerTitel werden festgelegt. Die linke obere Ecke von tfNeuerTitel hat die Koordinaten (20, 46). Seine Breite beträgt 190 und seine Höhe 20.
Zeile 28 tfNeuerTitel wird der contentPane hinzugefügt.

Beschriftung grafischer Komponenten bzw. Anzeige von Bildern: JLabel

Zur Beschriftung oder zur Anzeige eines Bildes eignet sich ein Objekt der Klasse JLabel.

Damit der Benutzer weiß, für welche Eingabe das Textfeld vorgesehen ist, beschriften wir es mit Hilfe eines JLabel-Objekts.

img/Abb_17_8_JLabel-Beschriftung.jpg
Abb. 17-8: Beschriftung mit Hilfe eines JLabel-Objekts
Quellcode-Ausschnitt
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package gui;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import java.awt.Font;

public class FensterMeineErsteGUI extends JFrame {

    private JPanel contentPane;
    private JTextField tfNeuerTitel;

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
        
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        tfNeuerTitel = new JTextField();
        tfNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNeuerTitel.setBounds(20, 46, 190, 20);
        contentPane.add(tfNeuerTitel);
        
        JLabel lbNeuerTitel = new JLabel("Neuer Fenstertitel:");
        lbNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNeuerTitel.setBounds(10, 18, 154, 14);
        contentPane.add(lbNeuerTitel);
    }

}

Abb. 17-9: Die Klasse FensterMeineErsteGUI
Erläuterungen
Zeile 30 Unter der Bezeichnung lbNeuerTitel wird eine lokale Variable vom Typ JLabel deklariert und ihr ein neu erzeugtes Objekt dieser Klasse zugewiesen. Dem Konstruktor wird dabei der anzuzeigende Text „Neuer Fenstertitel:” übergeben. Soll es möglich sein, auch aus anderen Methoden der Klasse heraus auf lbNeuerTitel zuzugreifen, muss lbNeuerTitel stattdessen als Attribut deklariert werden.
Zeile 31 Der in lbNeuerTitel angezeigte Text wird in der Schriftart Tahoma, mit dem Schriftstil Font.PLAIN2 und der Schriftgröße 12 formatiert.
Zeile 32 Position und Größe von lbNeuerTitel werden festgelegt. Die linke obere Ecke von lbNeuerTitel hat die Koordinaten (10, 18). Seine Breite beträgt 154 und seine Höhe 14.
Zeile 33 lbNeuerTitel wird der contentPane hinzugefügt.

Das im Ordner img gespeicherte Bild smilie.gif zeigen wir mit Hilfe eines JLabel-Objekts an.

img/Abb_17_10_JLabel-Bild.jpg
Abb. 17-10: Anzeige eines Bilds mit Hilfe eines JLabel-Objekts
Quellcode-Ausschnitt
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package gui;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import java.awt.Font;

public class FensterMeineErsteGUI extends JFrame {

    private JPanel contentPane;
    private JTextField tfNeuerTitel;

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
        
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        tfNeuerTitel = new JTextField();
        tfNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNeuerTitel.setBounds(20, 46, 190, 20);
        contentPane.add(tfNeuerTitel);
        
        JLabel lbNeuerTitel = new JLabel("Neuer Fenstertitel:");
        lbNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNeuerTitel.setBounds(10, 18, 154, 14);
        contentPane.add(lbNeuerTitel);
        
        JLabel lbSmilie = new JLabel("");
        lbSmilie.setBounds(230, 11, 72, 75);
        lbSmilie.setIcon(new ImageIcon(FensterMeineErsteGUI.class.getResource("/img/smilie.gif")));
        contentPane.add(lbSmilie);
    }

}

Abb. 17-11: Die Klasse FensterMeineErsteGUI
Erläuterungen
Zeile 36 Unter der Bezeichnung lbSmilie wird eine lokale Variable vom Typ JLabel deklariert und ihr ein neues Objekt der Klasse JLabel zugewiesen. Soll es möglich sein, auch aus anderen Methoden der Klasse heraus auf lbSmilie zuzugreifen, muss lbSmilie stattdessen als Attribut deklariert werden.
Zeile 37 Position und Größe von lbSmilie werden festgelegt. Die linke obere Ecke von lbNeuerTitel hat die Koordinaten (230, 11). Seine Breite beträgt 72 und seine Höhe 75.
Zeile 38 lbSmilie zeigt das im Ordner img gespeicherte Bild smilie.gif an. Der Ordner img befindet sich im Ordner src, der im Pfad jedoch nicht angegeben wird.
Zeile 39 lbSmilie wird der contentPane hinzugefügt.

Schaltfläche: JButton

Eine Schaltfläche lässt sich mit Hilfe eines Objekts der Klasse JButton erzeugen.

Für unser Beispiel benötigen wir zwei Schaltflächen. Die Schaltfläche mit der Aufschrift „Ändern“ soll dafür sorgen, dass der im Eingabefeld tfNeuerTitel angezeigte Text ausgelesen wird und dann den bisher in der Titelleiste des Fensters erscheinenden Text ersetzt. Die Schaltfläche mit der Aufschrift „Beenden“ soll die Java-Anwendung beenden.

img/Abb_17_1_FensterMeineErsteGUI.jpg
Abb. 17-12: Ein JButton-Objekt dient als Schaltfläche
Quellcode-Ausschnitt
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package gui;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FensterMeineErsteGUI extends JFrame {

    private JPanel contentPane;
    private JTextField tfNeuerTitel;

    public FensterMeineErsteGUI() {
        setTitle("Meine erste GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 150, 329, 169);
        
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        tfNeuerTitel = new JTextField();
        tfNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNeuerTitel.setBounds(20, 46, 190, 20);
        contentPane.add(tfNeuerTitel);
        
        JLabel lbNeuerTitel = new JLabel("Neuer Fenstertitel:");
        lbNeuerTitel.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNeuerTitel.setBounds(10, 18, 154, 14);
        contentPane.add(lbNeuerTitel);
        
        JLabel lbSmilie = new JLabel("");
        lbSmilie.setBounds(230, 11, 72, 75);
        lbSmilie.setIcon(new ImageIcon(FensterMeineErsteGUI.class.getResource("/img/smilie.gif")));
        contentPane.add(lbSmilie);

        JButton btAendern = new JButton("Ändern");
        btAendern.setFont(new Font("Tahoma", Font.PLAIN, 12));
        btAendern.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                aendereTitel();
            }
        });
        btAendern.setBounds(20, 82, 89, 25);
        contentPane.add(btAendern);

        JButton btBeenden = new JButton("Beenden");
        btBeenden.setFont(new Font("Tahoma", Font.PLAIN, 12));
        btBeenden.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                beenden();
            }
        });
        btBeenden.setBounds(121, 82, 89, 25);
        contentPane.add(btBeenden);
    }

    private void aendereTitel() {
        setTitle(tfNeuerTitel.getText());
    }

    private void beenden() {
        dispose();
        System.exit(0);
    }
}

Abb. 17-13: Die Klasse FensterMeineErsteGUI
Erläuterungen
Zeile 44 Unter der Bezeichnung btAendern wird eine lokale Variable vom Typ JButton deklariert und ihr ein neues Objekt der Klasse JButton zugewiesen. Dem Konstruktor wird dabei der anzuzeigende Text „Ändern” übergeben. Soll es möglich sein, auch aus anderen Methoden der Klasse heraus auf btAendern zuzugreifen, muss btAendern stattdessen als Attribut deklariert werden.
Zeile 45 Der in btAendern angezeigte Text wird in der Schriftart Tahoma, mit dem Schriftstil Font.PLAIN2 und der Schriftgröße 12 formatiert.
Zeile 46 Mit Hilfe der Methode addActionListener(l: ActionListener) kann an das jeweilige JButton-Objekt ein ActionListener-Objekt gekoppelt werden. Ein Listener lauscht auf Ereignisse die das Objekt, an das er gekoppelt ist, ihm meldet. Wird ihm ein Ereignis gemeldet, führt der Listener für diesen Zweck hinterlegte Anweisungen aus.
In unserem Fall führt der an btAendern gekoppelte ActionListener seine actionPerformed-Methode aus, sobald die Schaltfläche btAendern gedrückt wird. Diese ruft wiederum die private Methode aendereTitel() der Klasse FensterMeineErsteGUI auf.
Das ActionListener-Objekt wird mit Hilfe einer anonymen inneren Klasse erzeugt.
Anonyme innere Klasse

Eine anonyme innere Klasse besitzt keinen Klassennamen und wird innerhalb einer anderen Klasse deklariert. Sie ist eine Unterklasse der hinter new angegebenen Klasse. Innerhalb der geschweiften Klammern können Attribute und Methoden deklariert sowie geerbte Methoden der Oberklasse überschrieben werden. Das Schlüsselwort new sorgt dafür, dass automatisch ein Objekt der hier deklarierten anonymen Klasse erzeugt wird.

JAVA
new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        aendereTitel();
     }
});
Abb. 17-14: Anonyme innere Unterklasse von ActionListener

Der in Abbildung 17-14 zu sehende Audruck deklariert eine anonyme Unterklasse der Klasse ActionListener. Dabei wird die von ActionListener geerbte Methode actionPerformed(arg0: ActionEvent) so überschrieben, dass sie die private Methode aendereTitel() seiner äußeren Klasse FensterMeineErsteGUI aufruft (vgl. Abbildung 17-13, Zeile 48).

Das Schlüsselwort new sorgt dafür, dass automatisch ein Objekt dieser Klasse erzeugt wird. Dieses Objekt wird dann der Methode addActionListener(l: ActionListener) als Argument übergeben (vgl. Abbildung 17-13, Zeile 46 bis 50).

Zeile 51 Position und Größe von btAendern werden festgelegt. Die linke obere Ecke von btAendern hat die Koordinaten (20, 82). Seine Breite beträgt 89 und seine Höhe 25.
Zeile 52 btAendern wird der contentPane hinzugefügt.
Zeile 66 Der im Eingabefeld tfNeuerTitel angezeigte Text wird ausgelesen und ersetzt dann den bisher in der Titelleiste des Fensters erscheinenden Text.
Zeile 70 Das Fensters wird geschlossen.
Zeile 71 Die Java-Anwendung wird beendet.
Aufgabe

Aufgabe 17-1: Body Mass Index (GUI)

Erstellen Sie für die in Aufgabe 9-8 erstellte Anwendung „Body Mass Index“ folgende grafische Benutzeroberfläche:

img/Abb_17_15_FensterBMI_neu.jpg
Abb. 17-15: Die GUI-Klasse FensterBMI
Vorgaben
  • Nutzen Sie die in Aufgabe 9-8 erstellte Fachklasse Person.
  • Die in Abbildung 17-15 zu sehende Grafik steht als Bilddatei zur Verfügung.
  • Verwenden Sie zur Ausgabe der Daten Objekte der Klasse JTextField, deren Text mit Hilfe der Methode setEditable(b: boolean) vor Änderungen durch den Benutzer geschützt wird.
  • Durch das Betätigen der Schaltfläche Neu sollen alle Ein- und Ausgabefelder geleert werden.
  • Beim Programmstart und nach dem Betätigen der Schaltfläche Neu soll mit Hilfe der Anweisung tfVorname.requestFocus(); die Eingabemarke in das Eingabefeld tfVorname gesetzt werden.
  • Berücksichtigen Sie das Schichtenkonzept. Das heißt, ersetzen Sie die bisher genutzte UI-Klasse Benutzerkonsole durch die neu erstellte GUI-Klasse FensterBMI, ohne dass hierdurch Änderungen an der Fachklasse BodyMassIndex notwendig werden.
Lösung
Lösung
JAVA
package gui;

import app.BodyMassIndex;
import app.Person;
import myBib.Werkzeug;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.ImageIcon;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Component;
import javax.swing.Box;

public class FensterBMI extends JFrame {

    private JPanel contentPane;
    private JTextField tfGewicht;
    private JTextField tfGroesse;
    private JTextField tfBMI;
    private JTextField tfAuswertung;
    private JTextField tfVorname;
    private JTextField tfNachname;
    private JTextField tfPerson;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    FensterBMI frame = new FensterBMI();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    public FensterBMI() {
        setTitle("Body Mass Index");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 400, 361);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        tfGewicht = new JTextField();
        tfGewicht.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfGewicht.setBounds(267, 80, 87, 20);
        contentPane.add(tfGewicht);
        
        tfGroesse = new JTextField();
        tfGroesse.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfGroesse.setBounds(267, 108, 87, 20);
        contentPane.add(tfGroesse);
        
        tfBMI = new JTextField();
        tfBMI.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfBMI.setEditable(false);
        tfBMI.setBounds(154, 207, 199, 20);
        contentPane.add(tfBMI);
        
        tfAuswertung = new JTextField();
        tfAuswertung.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfAuswertung.setEditable(false);
        tfAuswertung.setBounds(154, 238, 199, 20);
        contentPane.add(tfAuswertung);
        
        JLabel lbGewichtInKg = new JLabel("Gewicht (in kg):");
        lbGewichtInKg.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbGewichtInKg.setBounds(155, 77, 102, 26);
        contentPane.add(lbGewichtInKg);
        
        JLabel lbGroesseInM = new JLabel("Größe (in m):");
        lbGroesseInM.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbGroesseInM.setBounds(155, 105, 102, 26);
        contentPane.add(lbGroesseInM);
        
        JLabel lbBMI = new JLabel("Der BMI beträgt:");
        lbBMI.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbBMI.setBounds(27, 204, 120, 26);
        contentPane.add(lbBMI);
        
        JLabel lbAuswertung = new JLabel("Auswertung:");
        lbAuswertung.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbAuswertung.setBounds(27, 233, 78, 30);
        contentPane.add(lbAuswertung);
        
        JLabel lbWaage = new JLabel("");
        lbWaage.setIcon(new ImageIcon(FensterBMI.class.getResource("/img/Waage.gif")));
        lbWaage.setBounds(25, 13, 110, 100);
        contentPane.add(lbWaage);
        
        JButton btBerechnen = new JButton("Berechnen");
        btBerechnen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                berechnen();
            }
        });
        btBerechnen.setBounds(141, 284, 100, 25);
        contentPane.add(btBerechnen);
        
        JButton btNeu = new JButton("Neu");
        btNeu.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                neu();
            }
        });
        btNeu.setBounds(20, 284, 100, 25);
        contentPane.add(btNeu);
        
        JButton btBeenden = new JButton("Beenden");
        btBeenden.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                beenden();
            }
        });
        btBeenden.setBounds(262, 284, 100, 25);
        contentPane.add(btBeenden);
        
        JLabel lbVorname = new JLabel("Vorname:");
        lbVorname.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbVorname.setBounds(155, 21, 102, 26);
        contentPane.add(lbVorname);
        
        tfVorname = new JTextField();
        tfVorname.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfVorname.setBounds(267, 24, 87, 20);
        contentPane.add(tfVorname);
        
        JLabel lbNachname = new JLabel("Nachname:");
        lbNachname.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNachname.setBounds(155, 49, 102, 26);
        contentPane.add(lbNachname);
        
        tfNachname = new JTextField();
        tfNachname.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNachname.setBounds(267, 52, 87, 20);
        contentPane.add(tfNachname);
        
        tfPerson = new JTextField();
        tfPerson.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfPerson.setEditable(false);
        tfPerson.setBounds(154, 176, 199, 20);
        contentPane.add(tfPerson);
        
        JLabel lbPerson = new JLabel("Person:");
        lbPerson.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbPerson.setBounds(27, 173, 120, 26);
        contentPane.add(lbPerson);
        
        tfVorname.requestFocus();
    }

    private void neu() {
        tfVorname.setText(null);
        tfNachname.setText(null);
        tfGewicht.setText(null);
        tfGroesse.setText(null);
        tfPerson.setText(null);
        tfBMI.setText(null);
        tfAuswertung.setText(null);
        tfGewicht.requestFocus();
    }

    private void beenden() {
        dispose();
        System.exit(0);
    }

    private void berechnen() {
        String vorname;
        String nachname;
        double gewicht;
        double groesse;
        Person person;
        double bmiWert;
        String bmiAuswertung;

        //Eingabewerte ermitteln
        vorname = tfVorname.getText();
        nachname = tfNachname.getText();
        gewicht = Double.parseDouble(tfGewicht.getText().replace(',', '.'));
        groesse = Double.parseDouble(tfGroesse.getText().replace(',', '.'));

        //Verarbeitung
        person = new Person(vorname, nachname);
        person.setGewicht(gewicht);
        person.setGroesse(groesse);
        bmiWert = person.berechneBMI();
        bmiWert = Math.round(bmiWert * 100) / 100.0;
        bmiWert = Werkzeug.runden(bmiWert, 2);
        bmiAuswertung = person.ermittleAuswertungBMI();

        //Ausgabe
        tfPerson.setText(person.getVorname() + " " + person.getNachname());
        tfBMI.setText(Double.toString(bmiWert).replace('.', ','));
        tfAuswertung.setText(bmiAuswertung);
    }
}

BMI auf zwei Nachkommastellen runden: 

Abb. 17-16: Die GUI-Klasse FensterBMI (Quellcode)
Aufgabe

Aufgabe 17-2: Halbjahresleistung III (GUI)

Erstellen Sie für die in Aufgabe 9-7 erstellte Anwendung „Noten II“ folgende grafische Benutzeroberfläche:

img/Abb_17_17_FensterHalbjahresleistung.jpg
Abb. 17-17: Die GUI-Klasse FensterHalbjahresleistung
Vorgaben
  • Nutzen Sie die in Aufgabe 9-7 erstellte Fachklasse Halbjahresleistung.
  • Die in Abbildung 17-17 zu sehende Grafik steht als Bilddatei zur Verfügung.
  • Verwenden Sie zur Ausgabe der Daten Objekte der Klasse JTextField, deren Text mit Hilfe der Methode setEditable(b: boolean) vor Änderungen durch den Benutzer geschützt wird.
  • Zentrieren Sie den in den Ein- und Ausgabefeldern angezeigten Text mit Hilfe der Anweisung objektnameTextfeld.setHorizontalAlignment(SwingConstants.CENTER);
  • Durch das Betätigen der Schaltfläche Neu sollen alle Ein- und Ausgabefelder geleert werden.
  • Beim Programmstart und nach dem Betätigen der Schaltfläche Neu soll die Eingabemarke in das Eingabefeld tfNoteKlArb1 gesetzt werden.
  • Berücksichtigen Sie das Schichtenkonzept. Das heißt, ersetzen Sie die bisher genutzte UI-Klasse Benutzerkonsole durch die neu erstellte GUI-Klasse FensterNoteII, ohne dass hierdurch Änderungen an der Fachklasse Noten notwendig werden.
Lösung
Lösung
JAVA
package gui;

import app.Halbjahresleistung;
import myBib.Werkzeug;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ImageIcon;
import javax.swing.border.EmptyBorder;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingConstants;

public class FensterHalbjahresleistung extends JFrame {

    private JPanel contentPane;
    private JTextField tfNoteKlArb1;
    private JTextField tfNoteKlArb2;
    private JTextField tfNoteMuendlich;
    private JTextField tfSchnitt;
    private JTextField tfZeugnisnote;

    public FensterHalbjahresleistung() {
        setTitle("Noten");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 372, 299);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        tfNoteKlArb1 = new JTextField();
        tfNoteKlArb1.setHorizontalAlignment(SwingConstants.CENTER);
        tfNoteKlArb1.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNoteKlArb1.setBounds(138, 21, 47, 23);
        contentPane.add(tfNoteKlArb1);
        
        tfNoteKlArb2 = new JTextField();
        tfNoteKlArb2.setHorizontalAlignment(SwingConstants.CENTER);
        tfNoteKlArb2.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNoteKlArb2.setBounds(138, 54, 47, 24);
        contentPane.add(tfNoteKlArb2);
        
        tfNoteMuendlich = new JTextField();
        tfNoteMuendlich.setHorizontalAlignment(SwingConstants.CENTER);
        tfNoteMuendlich.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfNoteMuendlich.setBounds(138, 89, 47, 23);
        contentPane.add(tfNoteMuendlich);
        
        tfSchnitt = new JTextField();
        tfSchnitt.setHorizontalAlignment(SwingConstants.CENTER);
        tfSchnitt.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfSchnitt.setEditable(false);
        tfSchnitt.setBounds(246, 162, 85, 23);
        contentPane.add(tfSchnitt);
        
        tfZeugnisnote = new JTextField();
        tfZeugnisnote.setHorizontalAlignment(SwingConstants.CENTER);
        tfZeugnisnote.setFont(new Font("Tahoma", Font.PLAIN, 12));
        tfZeugnisnote.setEditable(false);
        tfZeugnisnote.setBounds(246, 196, 85, 23);
        contentPane.add(tfZeugnisnote);
        
        JLabel lbNoteKlArb1 = new JLabel("1. Klassenarbeit:");
        lbNoteKlArb1.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNoteKlArb1.setBounds(32, 21, 102, 23);
        contentPane.add(lbNoteKlArb1);
        
        JLabel lbNoteKlArb2 = new JLabel("2. Klassenarbeit:");
        lbNoteKlArb2.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNoteKlArb2.setBounds(32, 55, 102, 23);
        contentPane.add(lbNoteKlArb2);
        
        JLabel lbNoteMuendlich = new JLabel("Mündliche Note:");
        lbNoteMuendlich.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNoteMuendlich.setBounds(32, 89, 102, 23);
        contentPane.add(lbNoteMuendlich);
        
        JLabel lbNotendurchschnitt = new JLabel("Notendurchschnitt:");
        lbNotendurchschnitt.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbNotendurchschnitt.setBounds(123, 162, 106, 23);
        contentPane.add(lbNotendurchschnitt);
        
        JLabel lbZeugnisnote = new JLabel("Zeugnisnote:");
        lbZeugnisnote.setFont(new Font("Tahoma", Font.PLAIN, 12));
        lbZeugnisnote.setBounds(123, 196, 106, 23);
        contentPane.add(lbZeugnisnote);
        
        JLabel lbZeugnis = new JLabel("");
        lbZeugnis.setIcon(new ImageIcon(FensterHalbjahresleistung.class.getResource("/img/Zeugnis.gif")));
        lbZeugnis.setBounds(22, 136, 91, 114);
        contentPane.add(lbZeugnis);
        
        JButton btBerechnen = new JButton("Berechnen");
        btBerechnen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                berechnen();
            }
        });
        btBerechnen.setBounds(226, 54, 101, 25);
        contentPane.add(btBerechnen);
        
        JButton btNeu = new JButton("Neu");
        btNeu.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                neu();
            }
        });
        btNeu.setBounds(226, 20, 101, 25);
        contentPane.add(btNeu);

        JButton btBeenden = new JButton("Beenden");
        btBeenden.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                beenden();
            }
        });
        btBeenden.setBounds(226, 88, 101, 25);
        contentPane.add(btBeenden);
    }
    
    private void neu() {
        tfNoteKlArb1.setText(null);
        tfNoteKlArb2.setText(null);
        tfNoteMuendlich.setText(null);
        tfSchnitt.setText(null);
        tfZeugnisnote.setText(null);
        tfNoteKlArb1.requestFocus();
    }

    private void beenden() {
        dispose();
        System.exit(0);
    }

    private void berechnen() {
        Halbjahresleistung halbjahresleistung = new Halbjahresleistung();
        double notenschnitt;
        
        halbjahresleistung.setNoteKlArb1( Integer.parseInt(tfNoteKlArb1.getText()) );
        halbjahresleistung.setNoteKlArb2( Integer.parseInt(tfNoteKlArb2.getText()) );
        halbjahresleistung.setNoteMuendlich( Integer.parseInt(tfNoteMuendlich.getText()) );

        notenschnitt = halbjahresleistung.berechneNotendurchschnitt();
        notenschnitt = Math.round(notenschnitt * 100) / 100.0;
        notenschnitt = Werkzeug.runden(notenschnitt, 2);

        tfSchnitt.setText(Double.toString(notenschnitt).replace(".", ","));
        tfZeugnisnote.setText(halbjahresleistung.ermittleZeugnisnote());
    }
}

Notendurchschnitt auf zwei Nachkommastellen runden: 

Abb. 17-18: Die GUI-Klasse FensterHalbjahresleistung (Quellcode)