Foliensatz 13

Werbung
CS1005
Objektorientierte Programmierung
Bachelor of Science (Informatik)
Th Letschert
Graphische Benutzerschnittstellen I
GUI erzeugen
Seite 1
© Th Letschert
GUI
GUI: Graphical User
Interface
Graphische
Benutzeroberfläche
Seite 2
Th Letschert
Beispiel: ein leeres Fenster
import javax.swing.JFrame;
public class SimpleGUIDemo {
public static void main(String[] args) {
JFrame frame
= new JFrame();
frame.setVisible(true);
System.out.println(“Main endet!“);
}
}
main
Erzeugt ein Fenster
und macht es sichtbar.
erzeugt GUI
Erweitertes Konzept von „Programm-Ausführung“:
Das Programm endet nicht mit dem Ende von main
... und auch nicht mit dem „Wegklicken“
des Fensters !
GUI-Code
endet
geht
weiter
Seite 3
Th Letschert
Beispiel: ein leeres Fenster
Hier Fenster wegklicken !
Programm endet
damit nicht.
Programm ist
aktiv !
Seite 4
Th Letschert
Threads: GUI ist unabhängig von main aktiv
import javax.swing.JFrame;
public class SimpleGUIDemo {
public static void main(String[] args) {
JFrame frame = new Jframe();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
System.out.println(“Main endet!“);
Wegklicken des
}
Wegklicken des
Fensters stoppt jetzt
}
Fensters stoppt jetzt
das Programm.
das Programm.
Das Programm besteht aus 2 Handlungssträngen (Threads):
- main und alle Methoden die von main direkt oder indirekt aktiviert werden
- die GUI
Um das Gesamt-Programm zu beenden, muss main und „die GUI“ enden.
Seite 5
Th Letschert
Mein-Thread und Event-Dispatcher
Benutzeraktionen
verarbeiten
EventDispatchingThread
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JFrame;
pub lic cla ss SimpleGUIDemo {
p ubli c s tatic void main(String[] args) {
JFrame
frame
= new JFrame();
GUIObjekte
Programmcode, beginnend
mit main, abarbeiten
Auf GUI-Objekte können zwei
unabhängige Handelnde (Threads)
zugreifen. Das kann zu
Konfliktsituationen und Problemen
führen.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS
E);
// Knopf (ein Widget) erzeugen
JBu tton button
= new
JBu tton("KlickMich!");
// Container des Fensters holen
Con tainer container = frame.getContentPane();
main
Thread
// Knpof in Fenster setzen
container.add(button);
//Fenstergroesse bestimmen
frame.setSize(400,500); // Breite Hoehe
frame.setVisible(true);
Programm: Objekte werden von 2 Threads (Aktivitäten)
bearbeitet
Seite 6
}
}
Th Letschert
Threads
Thread = (Handlungs-) Faden
Handlungsfaden / Thread:
zusammenhängende Folge von Aktionen
( Zuweisungen / Schleifen /
Methodenaufrufe, etc. )
wobei eine Aktion die nächste bedingt / verursacht /
beinflusst.
public class Test
{
public static
void main(String[]
args) {
....
}
}
main-Thread: bearbeitet
main und alle von dort
aufgerufenen Methoden
Main-Thread: alle Programme haben einen
Handlungsfaden, der mit main beginnt (mainThread)
Event-Dispatcher: GUI-Programme haben
zusätzlich einen Handlungsfaden, der die
Benutzeraktionen beobachtet (Event-DispatchingThread / Event-Dispatcher)
Event-Dispatcher: bearbeitet
Maus-Klicks, ...
Garbage-Collector: Im Hintergrund ist immer
noch ein weiterer Thread aktiv, der GarbageCollector (-Thread)
Java-Programm mit seinen
Threads
Seite 7
Garbage-Collector: sammelt
Speicher-Müll
Th Letschert
Ein Fenster mit einem Knopf
Widget ~ Window Gadget
(Fenster-Dings): Knopf, etc.
KlickMich
import javax.swing.JButton;
import javax.swing.JFrame;
public class SimpleGUIDemo {
der Knopf wird sehr groß sein!
public static void createGUI() {
JFrame
frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Knopf (ein Widget) erzeugen
JButton button
= new JButton("KlickMich!");
Fenster erzeugen
Widget erzeugen
// Knpof in Fenster setzen
frame.add(button);
Widget einfügen
}
}
//Fenstergroesse bestimmen
frame.setSize(400,500); // Breite Hoehe
frame.setVisible(true);
Größe bestimmen
sichtbar machen
public static void main(String[] args) { createGUI(); }
Seite 8
Th Letschert
Einfache GUI: Übersicht
Fenster erzeugen
Komponenten erzeugen
[ contentPane holen
Komponenten hinzufügen
Größe bestimmen
wegklickbar machen
sichtbar machen
frame = new JFrame..
button = new JButton...
getContentPane() nur bis Version 1.4]
frame.add(button);
frame.setSize
frame.setDefaultCloseOperation
frame.setVisible
Seite 9
Th Letschert
So soll es
aussehen!
GUI mit 2 Widgets
ein Label
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SimpleGUIDemo {
public static void createGUI() {
JFrame frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Knopf und Label erzeugen
JButton button = new JButton("KlickMich!");
JLabel label
= new JLabel("ein Label");
// Knopf und Label in Fenster setzen
frame.add(button);
frame.add(label);
frame.setSize(400,500); // Breite, Hoehe
frame.setVisible(true);
}
}
public static void main(String[] args){
createGUI();
}
Seite 10
Th Letschert
GUI mit 2 Widgets
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SimpleGUIDemo {
public static void createGUI() {
JFrame
frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Knopf und Label erzeugen
JButton button
= new JButton("KlickMich!");
JLabel label
= new JLabel("ein Label");
// Knopf und Label in Fenster setzen
frame.add(button);
frame.add(label);
}
}
frame.setSize(400,500); // Breite, Hoehe
frame.setVisible(true);
public static void main(String[] args){
createGUI();
}
Man sieht nur das Label!
Es füllt das gesamte Fenster
aus und deckt den Knopf ab.
Layout-Management
notwendig!
so sieht es aus – Igitt !
Seite 11
Th Letschert
Layout-Management
Layout-Management
Layout (Position/Größe) von Komponenten festlegen
Notwendig wenn in einem Fenster mehr als eine Komponente (Widget)
platziert wird.
Layout-Manager
Objekt, das dies übernimmt
Layout festlegen
Zuordnen eines Layout-Managers
Verschiedene Arten von Layout-Managern
Legen selbständig das Layout
nach verschiedenen Strategien
entsprechend der Benutzervorgaben fest:
Was – wie groß – wohin platzieren
Absolute Größen und Positionen der Komponenten müssen (und sollten
in der Regel) nicht angegeben werden
Seite 12
Th Letschert
Beispiel: Layout-Manager FlowLayout
import
import
import
import
java.awt.FlowLayout;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JLabel;
public class SimpleGUIDemo {
Flow-Layout positioniert von links nach rechts
public static void createGUI() {
und zeilenweise.
JFrame
frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Knopf und Label erzeugen
JButton button
= new JButton("KlickMich!");
JLabel label
= new JLabel("ein Label");
// Layout-Manager setzen
frame.setLayout( new FlowLayout() );
// Knopf und Label in Fenster setzen
frame.add(button);
frame.add(label);
frame mit Flow-Layout
ausstatten
frame.setSize(400,100); // Breite Hoehe
frame.setVisible(true);
}
}
public static void main(String[] args){ createGUI(); }
Seite 13
Th Letschert
einige wichtige Layout-Manager
GridLayout
Ordnet die Komponenten in einem Gitter (Grid) an.
Die Reihenfolge des Einfügens der Komponenten bestimmt ihre
Anordnung.
BorderLayout
Positioniert jeweils eine Komponente in 5 Regionen jeweils maximal eine
Komponente
Rand-Regionen: North, East, South, West (so klein wie möglich)
Zentral-Region: CENTER (restlicher Platz)
FlowLayout:
Positioniert Komponenten links-nach-rechts / oben-nach-unten
zeilenweise: Zeile voll, nächste Komponente in die nächste Zeile
BoxLayout
Ähnlich wie FlowLayout
aber Komponente können explizit in eine neue Zeile positioniert werden
Seite 14
Th Letschert
Layout-Manager : BoarderLayout
positioniert in eine von 5 Regionen:
NORTH
BorderLayout. NORTH
BorderLayout. SOUTH
BorderLayout. EAST
BorderLayout. WEST
BorderLayout. CENTER
Beispiel:
Frame im BoarderLayout mit 5 Labels.
JLabel labelN
=
JLabel labelS
=
JLabel labelE
=
JLabel labelW
=
JLabel labelC
=
JLabel("CENTER");
WEST
CENTER
EAST
SOUTH
new
new
new
new
new
JLabel("NORTH");
JLabel("SOUTH");
JLabel("EAST");
JLabel("WEST");
frame.setLayout(new BorderLayout());
frame.add(labelN,BorderLayout.NORTH);
frame.add(labelS,BorderLayout.SOUTH);
frame.add(labelE,BorderLayout.EAST);
frame.add(labelW,BorderLayout.WEST);
frame.add(labelC);
Seite 15
CENTER ist default-Wert.
Th Letschert
JPanel: GUIs hierarchisch aufbauen
JPanel: ein Container als Komponente
JFrame f = new JFrame( "BorderLayout" );
f.setLayout(new BorderLayout() );
f:JFrame (BorderLayout)
jp:JPanel (FlowLayout)
JPanel jp = new JPanel( new FlowLayout() );
f.add( jp, BorderLayout.NORTH );
jp.add( new JButton( "NORD-1" ) );
jp.add( new JButton( "NORD-2" ) );
f.add(
f.add(
f.add(
f.add(
new
new
new
new
JButton(
JButton(
JButton(
JButton(
"OST" ), BorderLayout.EAST );
"SUED" ), BorderLayout.SOUTH );
"WEST" ), BorderLayout.WEST );
"ZENTRUM" ), BorderLayout.CENTER );
JButton
NORD-1
JButton
NORD-2
JButton
OST
JButton
WEST
f.setSize( 300, 200 );
f.setVisible( true );
JButton
SUED
JButton
ZENTRUM
Hierarchischer Aufbau
Graphischer Aufbau
Seite 16
Th Letschert
BoxLayout
BoxLayout: Komponenten
stapeln
f: Jframe (BoarderLayout)
public class SimpleGUIDemo {
public static void createGUI() {
JFrame f = new JFrame( "BoxLayout" );
f.setLayout( new BorderLayout() );
jp:JPanel (BoxLayout)
JButton
NORD-1
JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout. Y_AXIS ));
jp.add(new JButton("NORD-1"));
jp.add(new JButton("NORD-2"));
f.add(jp, BorderLayout.NORTH);
f.add(new
f.add(new
f.add(new
f.add(new
JButton("OST"), BorderLayout.EAST );
JButton("SUED"), BorderLayout.SOUTH );
JButton("WEST"), BorderLayout.WEST );
JButton("ZENTRUM"),BorderLayout.CENTER);
NORD-2
JButton
OST
JButton
WEST
JButton
SUED
JButton
f.pack();
f.setVisible(true);
}
JButton
ZENTRUM
Komponente mit BoxLayout in
}
Komponente mit
public static void main(String[] args){ createGUI(); }
BoarderLayout
Seite 17
Th Letschert
Größe bestimmen: pack / setSize
Fenstergröße setzen
entweder explizit
einJFrame.setSize(Breite, Höhe);
oder implizit berechnet
einJFrame.pack();
pack bestimmt die Größe selbständig
aus der bevorzugten Größe der
Komponenten
Alle Komponenten möchten in einer
bestimmten Größe erscheinen.
Layout-Manager entscheiden über
Anordnung und tatsächlich zugestandene
Größe der Komponenten.
Verschiedene Layout-Manager haben
unterschiedliche Strategien zur
Bestimmung von Layout, Größe der
Komponenten und Einfluss des
Programmcodes auf beides.
Seite 18
JFrame f = new Jframe( ... );
f.setLayout( ... );
f.add(...);
...
f.add(...);
f.setSize( 200, 300 );
f.setVisible( true );
JFrame f = new
Jframe( ... );
f.setLayout( ... );
f.add(...);
...
f.add(...);
f.pack();
f.setVisible( true );
Th Letschert
Beispiel: Addier-GUI (1)
Addierer: Komponenten Planung:
Zwei Textfelder zur Eingabe
Ein Knopf um die Addition zu starten
Ein Textfeld zur Ausgabe
JFrame
JPanel
Operand 1
Operand 2
+
Ergebnis
JTextField
JButton
Seite 19
Th Letschert
Beispiel: Addier-GUI (2)
Addierer / Layout-Plan
Operand 1
Operand 2
+
Ergebnis
North
JFrame:
BorderLayout
Center
JFrame (BoarderLayout)
South
jp:JPanel (FlowLayout)
JTextField
JPanel
FlowLayout
op1TF
JTextField
op2TF
op1TF
resultTF
JTextField
op2TF
resultTF
JButton
plusB
plusB
Komponenten / Layout
Komponenten / hierarchische Struktur
Seite 20
Th Letschert
Beispiel: Addier-GUI (3)
public class AddiererGui {
public static void createGUI() {
JFrame
frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JButton
JTextField
JTextField
JTextField
plusB
op1TF
op2TF
resultTF
=
=
=
=
new
new
new
new
JButton("+");
JTextField(10);
JTextField(10);
JTextField(10);
North
Center
JPanel opPanel = new JPanel();
opPanel.setLayout( new FlowLayout() );
opPanel.add(op1TF);
opPanel.add(op2TF);
South
frame.add(opPanel,BorderLayout.NORTH);
frame.add(plusB,BorderLayout.CENTER);
frame.add(resultTF,BorderLayout.SOUTH);
resultTF
frame.pack();
frame.setVisible(true);
}
op1TF
}
public static void main(String[] args){ createGUI(); }
Seite 21
plusB
op2TF
Der Knopf
macht sich im
gesamten
Zentrum breit.
Igitt!
Th Letschert
Layout beeinflussen mit Labels und Panels
Formatieren mit Labels und Panels
Komponenten füllen ihren Platz aus: manchmal hässlich
Mit zusätzlichem JPanel und (leeren) Labels
kann formatiert werden
JPanel
JPanel
JPanel
JPanel
op1TF
op2TF
resultTF
op1TF
resultTF
plusB
JPanel
JPanel
op2TF
Knopf füllt das Zentrum
völlig aus. Igitt!
JLabel
Seite 22
plusB
Panel füllt das Zentrum
völlig aus. OK!
JLabel
Th Letschert
Layout beeinflussen mit Labels und Panels
JFrame
frame
= new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JButton
JTextField
JTextField
JTextField
plusB
op1TF
op2TF
resultTF
=
=
=
=
new
new
new
new
JButton(" + ");
JTextField(10);
JTextField(10);
JTextField(10);
JPanel opPanel = new JPanel();
opPanel.setLayout( new FlowLayout() );
opPanel.add(op1TF);
opPanel.add(op2TF);
JPanel plusPanel = new JPanel();
plusPanel.setLayout( new FlowLayout() );
plusPanel.add( new JLabel() );
plusPanel.add( plusB );
plusPanel.add( new JLabel() );
frame.add(opPanel,BorderLayout.NORTH);
frame.add(plusPanel,BorderLayout. CENTER );
frame.add(resultTF,BorderLayout.SOUTH);
Zentrum:
leerers Label, Knopf, leeres Label
frame.pack();
frame.setVisible(true);
Seite 23
Th Letschert
Komponenten gestalten / Addier-GUI (4)
Aussehen und Verhalten der Komponenten kann vielfältig
beeinflusst werden
●
●
●
Formatiertierte Textfelder
Schriftart
....
JButton
JTextField
plusB= new JButton(" + ");
op1TF= new JFormattedTextField(
new
java.text.DecimalFormat());
JTextField op2TF= new JFormattedTextField(
new
java.text.DecimalFormat());
op1TF.setColumns(5);
op2TF.setColumns(5);
op1TF.setHorizontalAlignment(JTextField.RIGHT);
op2TF.setHorizontalAlignment(JTextField.RIGHT);
op1TF.setFont(new Font("monspaced", Font.PLAIN, 20));
op2TF.setFont(new Font("monspaced", Font.PLAIN, 20));
JTextField resultTF
= new JTextField(10);
resultTF.setFont(new Font("monspaced", Font.PLAIN, 20));
resultTF.setEditable(false);
Seite 24
Nur Zahleingaben
annehmen
Schriftstil und
Ausrichtung
festlegen
Eingaben in
Ausgabefeld
verhindern
Swing-Tutorial / API-Doku (Sun)
für solche „Tricks“ konsultieren!
Th Letschert
Quellcode-Organisation : GUI-Klasse definieren
Klassen für GUI-Objekte definieren
• statt
... main (...) {
JFrame einFenster = new ....
einFenster.add(eineKomponente);
.....
• besser: JFrame-Klasse definieren, organisiert sich selbst
class MeineGUIKlasse extends JFrame {
private meineKomponenten...
....
add(eineKomponente); ( oder this.add(eineKomponente); )
....
}
...
MeineGUIKlasse einGUIObjekt = new MeineGUIKlasse();
Seite 25
Th Letschert
Quellcode-Organisation / Addier-GUI (5/1)
public class AddiererGUI extends JFrame {
private JButton
plusB;
private JTextField op1TF;
JFrame frame = new JFrame();
private JTextField op2TF;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
private JTextField resultTF; frame.setLayout(new BorderLayout());
...
public AddiererGUI() {
super("Addierer");
initView();
}
kein JFrame erzeugen, Objekt selbst ist JFrame
Konstruktor ruft initView
initView erzeugt GUI-Elemente
private void initView() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
plusB
= new JButton(" + ");
op1TF
= new JFormattedTextField(new java.text.DecimalFormat());
op2TF
= new JFormattedTextField(new java.text.DecimalFormat());
op1TF.setColumns(5);
op2TF.setColumns(5);
op1TF.setHorizontalAlignment(JTextField.RIGHT);
op2TF.setHorizontalAlignment(JTextField.RIGHT);
op1TF.setFont(new Font("monspaced", Font.PLAIN, 20));
op2TF.setFont(new Font("monspaced", Font.PLAIN, 20));
···>
Seite 26
Th Letschert
Quellcode-Organisation / Addier-GUI (5/2)
resultTF = new JTextField(10);
resultTF.setFont(new Font("monspaced", Font.PLAIN, 20));
resultTF.setEditable(false);
JPanel opPanel = new JPanel();
opPanel.setLayout( new FlowLayout() );
opPanel.add(op1TF);
opPanel.add(op2TF);
JPanel
plusPanel = new JPanel();
plusPanel.setLayout( new FlowLayout() );
plusPanel.add( new JLabel() );
plusPanel.add( plusB );
plusPanel.add( new JLabel() );
this.add(opPanel,BorderLayout.NORTH);
this.add(plusPanel,BorderLayout.CENTER);
this.add(resultTF,BorderLayout.SOUTH);
this.pack();
}// Ende initView
}// Ende AddiererGUI
Seite 27
Th Letschert
Quellcode-Organisation / Addier-GUI (6)
public class Addierer {
public static void main(final String[] args){
AddiererGUI addierGUI = new AddiererGUI();
addierGUI.setVisible(true);
}
}
Eine Hauptklasse erzeugt in
main ein GUI-Objekt und
aktiviert es (macht es
sichtbar).
Code-Organisation:
Paket
mit 2 Klassen:
Addierer
AddiererGUI
Seite 28
addierer
Hauptklasse
Erzeugen, Kontrollieren
GUI-Elemente
Th Letschert
Zugehörige Unterlagen
Herunterladen