Grafical User Interface

Im Unterschied zur text-basierten Interaktion wird mit GUI eine Benutzerschnittstelle bezeichnet, die eine grafische Oberfläche verwendet und Interaktion mit der Maus ermöglicht. Java GUI Komponenten dienen zum Erstellen von Fenstern, Buttons, Grafiken usw. Für viele GUI Komponenten gibt es im Java API zwei Versionen:

NICHT in derselben Applikation beide verwenden!

Begriffe:

SwingDemo

import javax.swing.*;

public class SwingDemo extends JFrame {

  public static void main(String[] args) {
    new SwingDemo("SwingDemo");
  }

  SwingDemo(String title) {
    super(title);
    JLabel label = new JLabel("This is the Swing Demo!");
    getContentPane().add(label);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
    setVisible(true);
  }

}

Layouts, Events

Layouts ienen zur Anordnung der Elemente, die auch nach Resize des Fensters erhalten bleiben soll.

Events wie Click auf Button, Window Close usw. Events können mit ActionListeners behandelt werden.

Beispiel: SwingCounterDemo. Bei dieser Variante muß unsere Klasse das Interface ActionListener() implementieren, mit der Methode actionPerformed(), wo wir die einzelnen Aktionen behandeln.

Die Verbindung zwischen den einzelnen GUI-Elementen und der actionPerformed() Methode stellen wir mit addActionListener() her. Da SwingCounterDemo das ActionListener() Interface implementiert, können wir 'this' als ActionListener verwenden.

Alternativ können wir den ActionListener auch als inner class definieren:

  final JTextField tf = new JTextField(5);
  tf.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
      String s = tf.getText();
    }
  });

Weitere Beispiele: noch eine Swing-Variante des Counters, und eine AWT-Variante.

Grafik

Natürlich stehen in Swing und AWT auch grafische Grundoperationen zur Verfügung wie das Zeichnen von Linien sowie Rechtecken und anderen geometrischen Formen. Dazu gibt es verschiedene Möglichkeiten; in unserem Beispiel wird die eigene Klasse MyClass als JPanel definiert und überschreibt dann die paint() Methode, die als Parameter den aktuellen graphics context erhält und Zeichenoperationen ausführt:

class MyClass extends JPanel {

  ...
  public void paint(Graphics g) {
    ...
    g.drawLine(10,30,100,200);
  }
}

Bei den Koordinaten ist zu beachten, daß der Ursprung links OBEN liegt.

Die paint() Methode wird NICHT von unserer Applikation aufgerufen, sondern von der JRE, und zwar immer dann, wenn es notwendig ist, d.h. wenn die Komponente tatsächlich neu gezeichnet werden muß; z.B. wenn eine Applikation gestartet wird, aber auch wenn ein Fenster wieder sichtbar wird, das vorher verdeckt war, usw.

Ist von der Applikationslogik aus anderen Gründen ein Neuzeichnen erforderlich, dann kann das mit repaint() bewirkt werden. In ThreadTest.java sehen Sie, wie das mit einem Thread gelöst werden kann, der in periodischen Abständen unabhängig von sonstigen Interaktionen das Neuzeichnen übernimmt.

Aufgabe 1: Finden Sie in der Java API Dokumentation heraus, welche Operationen mit einem Graphics Objekt möglich sind, und schreiben Sie eine ganz einfache kleine Applikation, die einige Linien und andere grafische Elemente zeichnet.

Aufgabe 2: Setzen Sie auch die GUI-Elemente wie Buttons usw. ein, damit die Grafik interaktiv veränderbar wird, z.B. Ändern der Farbe.

Aufgabe

Wir wollen die GUI Komponenten in einer etwas umfangreicheren Aufgabe einsetzen. Es geht um die Steuerung eines Bootes. Folgendes soll implementiert werden:

  1. Ein Boot wird als bewegliches Objekt auf einer Wasserfläche dargestellt. Es hat die Eigenschaften Standort (X/Y Koordinaten), Geschwindkeit in Knoten, und Richtung (Kurs in Grad von 0 bis 360).
  2. Gesteuert wird mit dem Steuerrad, das kurz nach Steuerbord und Backbord gelegt werden kann, was jeweils eine Kursänderung von 11.25 Grad (1 Strich) bewirkt. Zwei Buttons sind ausreichend.
  3. Bei Fahrt unter Motor kann die Geschwindigkeit gewählt werden. Es soll folgende Möglichkeiten (Buttons) geben:
  4. Die Bewegung das Bootes wird durch Neuzeichnen in bestimmten Zeitintervallen dargestellt (z. B. alle 50 Millisekunden):
  5. Der aktuelle Wind wird als Pfeil im rechten oberen Eck des Navigationsbereichs dargestellt.
  6. Das Boot wird nicht als Kreis dargestellt, sondern in einer Form, die Bug und Heck erkennen läßt. Außerdem soll es gemäß dem aktuellen Kurs ausgerichtet sein, d.h. bei z.B. Kurs 090 soll der Bug nach rechts weisen.
  7. Bei Fahrt unter Segel ergibt sich die Geschwindigkeit in Knoten aus dem Winkel zwischen Kurs und Wind gemäß Diagramm. Ein Knoten entspricht einer Seemeile pro Stunde, das sind 1.85 km/h.
  8. Alle Parameter, die im Code bisher als Konstanten definiert wurden, sollen über das GUI geändert werden können. Dabei können Textfelder, aber auch Pulldown menues, Check boxes, Radio buttons usw. eingesetzt werden.
  9. Die Trägheit des Bootes wird realistisch modelliert, d.h. die Geschwindigkeit in Knoten ändert sich nur langsam, wenn sich der Vortrieb ändert.
  10. Unter Motor kann auch auf Rückwärtsfahrt geschalten werden, dann wirkt zunächst nur der Radeffekt als seitliches Auswandern des Hecks (nach backbord), erst nach einigen Sekunden beginnt das Boot rückwärts Fahrt aufzunehmen, und erst dann beginnt das Ruder zu wirken.
  11. Das Boot ist nicht allein auf dem Wasser, sondern es gibt auch eine konfigurierbare Anzahl anderer Segelboote, die sich zufaellig bewegen, allerdings
  12. Kollisionen von Booten werden entdeckt, und die Weiterfahrt beider Boote wird entsprechend beeinflußt.

Der gesamte Code wird mit javadoc dokumentiert, d.h. alle Klassen und Methoden werden mit Kommentaren versehen.