GUI-Programmierung
      Michael Zilske
Kommandozeile
Kommandozeile

•   Stammt direkt vom
    Teletype-Arbeitsplatz ab:

    •   Anfrage wird
        eingegeben

    •   Antwort wird
        ausgedruckt
public static void main(String[] args) throws IOException {
	 BufferedReader in = new BufferedReader(
       new InputStreamReader(System.in));
	 System.out.println("Gib den Namen Deiner Katze ein.");
	 String correctAnswer = "Telefonmann";
	 String input = in.readLine();
	 while (!correctAnswer.equals(input)) {
	 	 System.out.println("Das ist doch kein Name für eine Katze!");
	 	 input = in.readLine();
	 }
	 System.out.println("Ist besser.");
}

Gib den Namen Deiner Katze ein.
Peter
Das ist doch kein Name für eine Katze!
Orang-Utan Klaus
Das ist doch kein Name für eine Katze!
Telefonmann
Ist besser.
Kommandozeile

• Die dialogorientierte Schnittstelle, bei der
  Dinge nacheinander abgefragt werden, ist
  etwas aus der Mode.
• Kommandozeilen sind aber nach wie vor
  Teil jedes Betriebssystems und vieler
  komplexer Softwarepakete (z.B. MATLAB).
Graphical User Interface (GUI)
Typische GUI-Elemente
•   Fenster    •   Radiobutton

•   Icon       •   Schieberegler

•   Menü       •   Bildlaufleiste

•   Zeiger     •   Liste

•   Knopf      •   Tabelle

•   Checkbox   •   ...
Visuelle Sprache

• Von unterschiedlichen GUI-Elementen wird
  per Konvention ein bestimmtes Verhalten
  erwartet, zum Beispiel
 • Checkbox
 • Radiobutton
Bibliothek
• GUI-Elemente werden von einer Bibliothek
  bereitgestellt, die mehr oder weniger zur
  verwendeten Plattform gehört:
 • Windows, Mac OS X, Android, iPhone
 • Linux hat zwei: Qt und GTK
 • Java hat zwei: Swing und SWT
Know your library
• Es führt kein Weg daran vorbei, die
  Dokumentation der jeweiligen Bibliothek
  zu lesen.
• Dafür bekommt man viel Funktionalität frei
  Haus, und außerdem Entscheidungen
  abgenommen.
• Meistens gibt es auch noch ein Style Guide.
Gute Ausstattung

• Internationalisierung
• Barrierefreiheit
• Komplexe Elemente, z.B. Browserfenster
• Nutzung von Infrastruktur: Maps, Location
API
• Die dokumentierte Schnittstelle, über die
  die Anwendungssoftware mit der Plattform
  kommuniziert, nennt man API (Application
  Programming Interface).
• Besteht grob aus Befehlen (was ich mit der
  Plattform tun kann) und Events (was mir
  von der Plattform aus passieren kann).
Befehle

• Füge in die Linke obere Ecke des Fensters
  einen Knopf mit der Aufschrift a ein.
• Ändere den Text, der im Textfeld x
  angezeigt wird, zu y.
• Lies den Text aus, den der Benutzer in das
  Eingabefeld e eingegeben hat.
Events
• Ein Event (Ereignis) wird dem Programm
  signalisiert, sobald etwas interessantes
  passiert:
 • Benutzer klickt mit der Maus auf Knopf x.
 • Eine Email kommt.
 • Eine Zeitspanne t ist abgelaufen.
 • Der Rechner wird heruntergefahren.
Komponenten
• In einer GUI-Bibliothek mit einer
  objektorientierten API sind die GUI-Elemente
  Objekte, mit denen diese Dinge getan
  werden.
• Für alle Standard-GUI-Elemente werden
  Klassen bereitgestellt. Um ein Element mit
  spezialisiertem Verhalten zu erzeugen, muss
  eine eigene Klasse erstellt werden.
Konkret: Swing
• Komponentenklassen fangen mit J an.
• Zum Beispiel
 • JButton (ein Druckknopf)
 • JFrame (ein “großes” Fenster mit allem
    drum und dran)
 • JPanel (eine Fläche, auf der andere
    Komponenten angeordnet sind)
Komponenten sind
       Container

• In viele Komponenten kann man andere
  Komponenten hineintun.
• Ein JPanel zum Beispiel kann andere
  Komponenten aufnehmen und auf
  unterschiedliche Arten anordnen.
GridLayout layout = new GridLayout(2,1);
JPanel panel = new JPanel(layout);
	 	
JButton button = new JButton("Klick mich");
panel.add(button);
	 	
JButton button2 = new JButton("Oder mich");
panel.add(button2);
LayoutManager
• Die LayoutManager ermöglichen es,
  Komponenten koordinatenfrei, regelbasiert
  anzuordnen.
• Ein bisschen wie HTML: Dort gibt man ja
  auch nicht absolut vor, was wo stehen soll,
  sondern erlaubt dem Browser, die Dinge so
  anzuordnen, dass sie passen. Sollte man
  jedenfalls.
Deklarative GUI
• ... und in der Tat gibt es GUI-Frameworks, in
  denen man die Oberfläche nicht prozedural
  zusammenprogrammiert, sondern in einer
  XML-Datei beschreibt.
• ... was dann auch wiederum ein graphisches
  Werkzeug tun kann.
• Swing gehört nicht dazu.
Beinahe deklarative
          GUI
• Trotzdem sollte der Code, der die GUI
  aufbaut, sich wie eine Seitenbeschreibung
  lesen. Er soll nur die GUI-Elemente
  zusammenstöpseln und sonst nichts.
• Es gibt sogar graphische GUI-Builder, die
  solchen Code generieren. Z.B. NetBeans.
GridLayout
• Ordnet mehrere Dinge kachelförmig an
• mit wählbarer Reihen-/Spaltenzahl
• und macht alle Elemente gleich groß
BorderLayout
• Hat eine Mittelkomponente und je eine
  linke/rechte/obere/untere Komponente.
• Mittelkomponente ist so groß, wie sie kann.
• Randkomponenten sind so groß, wie sie
  müssen.
• Perfekt für: Anwendungsprogramme mit
  Werkzeugleisten oder dergleichen.
GridBagLayout

• Komplex
• Ordnet die Elemente in einer Tabelle an,
  und jedes Element kann mehrere Zeilen/
  Spalten überspannen
Layout Hints
• Der LayoutManager einer Komponente
  wird über zusätzliche Parameter beim
  Hinzufügen der Elemente bedient, die
  spezifisch für den Layout-Manager sind.

   contentPane.setLayout(new BorderLayout());
   contentPane.add(panel, BorderLayout.NORTH);
   contentPane.add(text, BorderLayout.CENTER);
JLabel
• Ein JLabel ist ein einfaches Textfeld, dessen
   Inhalt vom Programm gesetzt werden kann.

label = new JLabel(“Hallo.”,SwingConstants.CENTER);
contentPane.add(label, BorderLayout.CENTER);

... anderswo:

label.setTest(“Tschüß.”);
Events
• In einer objektorientierten GUI-Bibliothek
  kommen die Events bei den Komponenten-
  Objekten an, denen sie passiert sind.
• Zum Beispiel bei einem Knopf: Dass er
  gedrückt wurde.
• Oder bei einem Fenster: Dass seine Größe
  geändert wurde.
Konkret: Swing
• Komponenten delegieren die Bearbeitung
  der Events, die bei ihnen ankommen, an
  Listener-Objekte, die bei ihnen registriert
  werden können.
• Am Listener-Objekt wird dann von der
  Komponente eine bestimmte Interface-
  Methode aufgerufen und ein Event-Objekt
  übergeben, in dem steht, was passiert ist.
...

        JButton button = new JButton("Klick mich");
    	   button.setActionCommand("knopf1");
    	   button.addActionListener(this);
    	   panel.add(button);
	   	
    	   JButton button2 = new JButton("Oder mich");
    	   button2.setActionCommand("knopf2");
    	   button2.addActionListener(this);
    	   panel.add(button2);

        ...

public void actionPerformed(ActionEvent e) {
	 if (e.getActionCommand().equals("knopf1")) {
	 	 clickCounter++;
	 	 text.setText(labelText());
	 } else if (e.getActionCommand().equals("knopf2")) {
           clickCounter--;
	 	 text.setText(labelText());
   }
}
Demo
Problem
• In Event-Handlern darf man keine lang
  dauernden Dinge tun. Nichts ausrechnen,
  keine Dateien einlesen, nichts.
• Sonst sieht der Benutzer einen
  eingefrorenen Bildschirm und denkt, es ist
  etwas kaputt.
• Das ist nicht spezifisch für Swing, sondern
  gibt es in ähnlicher Form immer.
Problem
• Das Problem ist sogar ernster: In einem
  ActionListener in einer Schleife mehrmals
  ein Textfeld aktualisieren geht überhaupt
  nicht, weil Swing erst nach Ausstieg aus
  dem ActionListener dazu kommt, das
  Textfeld neu zu malen.
• Das Problem ist also mehr als kosmetisch.
Lösung: SwingWorker
• Eine Klasse, die “etwas zu tun” darstellt.
• Eigene Unterklasse erzeugen.
• In doInBackground() die Arbeit machen und
  regelmäßig publish() aufrufen.
• In process() die GUI aktualisieren.
• Dann muss man nichts weiter über Threads
  wissen.
class   PrimeNumbersTask extends SwingWorker<List<Integer>,Integer> {
	 	      PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
	 	      	 //initialize
	 	      }

	   	   @Override
	   	   public List<Integer> doInBackground() {
	   	   	 while (! enough && ! isCancelled()) {
	   	   	 	 number = nextPrimeNumber();
	   	   	 	 publish(number);
	   	   	 }
	   	   	 return numbers;
	   	   }
	
    	   @Override
    	   protected void process(List<Integer> chunks) {
    	   	 for (int number : chunks) {
    	   	 	 textArea.append(number + "n");
    	   	 }
    	   }
}
Nächtes mal


• Was man tun muss, wenn man selbst etwas
  malen will.

OOP Graphik 1

  • 1.
    GUI-Programmierung Michael Zilske
  • 2.
  • 3.
    Kommandozeile • Stammt direkt vom Teletype-Arbeitsplatz ab: • Anfrage wird eingegeben • Antwort wird ausgedruckt
  • 4.
    public static voidmain(String[] args) throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); System.out.println("Gib den Namen Deiner Katze ein."); String correctAnswer = "Telefonmann"; String input = in.readLine(); while (!correctAnswer.equals(input)) { System.out.println("Das ist doch kein Name für eine Katze!"); input = in.readLine(); } System.out.println("Ist besser."); } Gib den Namen Deiner Katze ein. Peter Das ist doch kein Name für eine Katze! Orang-Utan Klaus Das ist doch kein Name für eine Katze! Telefonmann Ist besser.
  • 5.
    Kommandozeile • Die dialogorientierteSchnittstelle, bei der Dinge nacheinander abgefragt werden, ist etwas aus der Mode. • Kommandozeilen sind aber nach wie vor Teil jedes Betriebssystems und vieler komplexer Softwarepakete (z.B. MATLAB).
  • 6.
  • 7.
    Typische GUI-Elemente • Fenster • Radiobutton • Icon • Schieberegler • Menü • Bildlaufleiste • Zeiger • Liste • Knopf • Tabelle • Checkbox • ...
  • 8.
    Visuelle Sprache • Vonunterschiedlichen GUI-Elementen wird per Konvention ein bestimmtes Verhalten erwartet, zum Beispiel • Checkbox • Radiobutton
  • 9.
    Bibliothek • GUI-Elemente werdenvon einer Bibliothek bereitgestellt, die mehr oder weniger zur verwendeten Plattform gehört: • Windows, Mac OS X, Android, iPhone • Linux hat zwei: Qt und GTK • Java hat zwei: Swing und SWT
  • 10.
    Know your library •Es führt kein Weg daran vorbei, die Dokumentation der jeweiligen Bibliothek zu lesen. • Dafür bekommt man viel Funktionalität frei Haus, und außerdem Entscheidungen abgenommen. • Meistens gibt es auch noch ein Style Guide.
  • 11.
    Gute Ausstattung • Internationalisierung •Barrierefreiheit • Komplexe Elemente, z.B. Browserfenster • Nutzung von Infrastruktur: Maps, Location
  • 12.
    API • Die dokumentierteSchnittstelle, über die die Anwendungssoftware mit der Plattform kommuniziert, nennt man API (Application Programming Interface). • Besteht grob aus Befehlen (was ich mit der Plattform tun kann) und Events (was mir von der Plattform aus passieren kann).
  • 13.
    Befehle • Füge indie Linke obere Ecke des Fensters einen Knopf mit der Aufschrift a ein. • Ändere den Text, der im Textfeld x angezeigt wird, zu y. • Lies den Text aus, den der Benutzer in das Eingabefeld e eingegeben hat.
  • 14.
    Events • Ein Event(Ereignis) wird dem Programm signalisiert, sobald etwas interessantes passiert: • Benutzer klickt mit der Maus auf Knopf x. • Eine Email kommt. • Eine Zeitspanne t ist abgelaufen. • Der Rechner wird heruntergefahren.
  • 15.
    Komponenten • In einerGUI-Bibliothek mit einer objektorientierten API sind die GUI-Elemente Objekte, mit denen diese Dinge getan werden. • Für alle Standard-GUI-Elemente werden Klassen bereitgestellt. Um ein Element mit spezialisiertem Verhalten zu erzeugen, muss eine eigene Klasse erstellt werden.
  • 16.
    Konkret: Swing • Komponentenklassenfangen mit J an. • Zum Beispiel • JButton (ein Druckknopf) • JFrame (ein “großes” Fenster mit allem drum und dran) • JPanel (eine Fläche, auf der andere Komponenten angeordnet sind)
  • 17.
    Komponenten sind Container • In viele Komponenten kann man andere Komponenten hineintun. • Ein JPanel zum Beispiel kann andere Komponenten aufnehmen und auf unterschiedliche Arten anordnen.
  • 18.
    GridLayout layout =new GridLayout(2,1); JPanel panel = new JPanel(layout); JButton button = new JButton("Klick mich"); panel.add(button); JButton button2 = new JButton("Oder mich"); panel.add(button2);
  • 19.
    LayoutManager • Die LayoutManagerermöglichen es, Komponenten koordinatenfrei, regelbasiert anzuordnen. • Ein bisschen wie HTML: Dort gibt man ja auch nicht absolut vor, was wo stehen soll, sondern erlaubt dem Browser, die Dinge so anzuordnen, dass sie passen. Sollte man jedenfalls.
  • 20.
    Deklarative GUI • ...und in der Tat gibt es GUI-Frameworks, in denen man die Oberfläche nicht prozedural zusammenprogrammiert, sondern in einer XML-Datei beschreibt. • ... was dann auch wiederum ein graphisches Werkzeug tun kann. • Swing gehört nicht dazu.
  • 21.
    Beinahe deklarative GUI • Trotzdem sollte der Code, der die GUI aufbaut, sich wie eine Seitenbeschreibung lesen. Er soll nur die GUI-Elemente zusammenstöpseln und sonst nichts. • Es gibt sogar graphische GUI-Builder, die solchen Code generieren. Z.B. NetBeans.
  • 22.
    GridLayout • Ordnet mehrereDinge kachelförmig an • mit wählbarer Reihen-/Spaltenzahl • und macht alle Elemente gleich groß
  • 23.
    BorderLayout • Hat eineMittelkomponente und je eine linke/rechte/obere/untere Komponente. • Mittelkomponente ist so groß, wie sie kann. • Randkomponenten sind so groß, wie sie müssen. • Perfekt für: Anwendungsprogramme mit Werkzeugleisten oder dergleichen.
  • 24.
    GridBagLayout • Komplex • Ordnetdie Elemente in einer Tabelle an, und jedes Element kann mehrere Zeilen/ Spalten überspannen
  • 25.
    Layout Hints • DerLayoutManager einer Komponente wird über zusätzliche Parameter beim Hinzufügen der Elemente bedient, die spezifisch für den Layout-Manager sind. contentPane.setLayout(new BorderLayout()); contentPane.add(panel, BorderLayout.NORTH); contentPane.add(text, BorderLayout.CENTER);
  • 26.
    JLabel • Ein JLabelist ein einfaches Textfeld, dessen Inhalt vom Programm gesetzt werden kann. label = new JLabel(“Hallo.”,SwingConstants.CENTER); contentPane.add(label, BorderLayout.CENTER); ... anderswo: label.setTest(“Tschüß.”);
  • 27.
    Events • In einerobjektorientierten GUI-Bibliothek kommen die Events bei den Komponenten- Objekten an, denen sie passiert sind. • Zum Beispiel bei einem Knopf: Dass er gedrückt wurde. • Oder bei einem Fenster: Dass seine Größe geändert wurde.
  • 28.
    Konkret: Swing • Komponentendelegieren die Bearbeitung der Events, die bei ihnen ankommen, an Listener-Objekte, die bei ihnen registriert werden können. • Am Listener-Objekt wird dann von der Komponente eine bestimmte Interface- Methode aufgerufen und ein Event-Objekt übergeben, in dem steht, was passiert ist.
  • 29.
    ... JButton button = new JButton("Klick mich"); button.setActionCommand("knopf1"); button.addActionListener(this); panel.add(button); JButton button2 = new JButton("Oder mich"); button2.setActionCommand("knopf2"); button2.addActionListener(this); panel.add(button2); ... public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("knopf1")) { clickCounter++; text.setText(labelText()); } else if (e.getActionCommand().equals("knopf2")) { clickCounter--; text.setText(labelText()); } }
  • 30.
  • 31.
    Problem • In Event-Handlerndarf man keine lang dauernden Dinge tun. Nichts ausrechnen, keine Dateien einlesen, nichts. • Sonst sieht der Benutzer einen eingefrorenen Bildschirm und denkt, es ist etwas kaputt. • Das ist nicht spezifisch für Swing, sondern gibt es in ähnlicher Form immer.
  • 32.
    Problem • Das Problemist sogar ernster: In einem ActionListener in einer Schleife mehrmals ein Textfeld aktualisieren geht überhaupt nicht, weil Swing erst nach Ausstieg aus dem ActionListener dazu kommt, das Textfeld neu zu malen. • Das Problem ist also mehr als kosmetisch.
  • 33.
    Lösung: SwingWorker • EineKlasse, die “etwas zu tun” darstellt. • Eigene Unterklasse erzeugen. • In doInBackground() die Arbeit machen und regelmäßig publish() aufrufen. • In process() die GUI aktualisieren. • Dann muss man nichts weiter über Threads wissen.
  • 34.
    class PrimeNumbersTask extends SwingWorker<List<Integer>,Integer> { PrimeNumbersTask(JTextArea textArea, int numbersToFind) { //initialize } @Override public List<Integer> doInBackground() { while (! enough && ! isCancelled()) { number = nextPrimeNumber(); publish(number); } return numbers; } @Override protected void process(List<Integer> chunks) { for (int number : chunks) { textArea.append(number + "n"); } } }
  • 35.
    Nächtes mal • Wasman tun muss, wenn man selbst etwas malen will.