GUI Design Universität Paderborn Prof. Dr. Stefan Böttcher Java Swing und AWT 1 Gui Design Universität Paderborn Prof. Dr. Stefan Böttcher Von „Hand“ Mittels visuellem GUI Designer 2 Warum „von Hand“? Universität Paderborn Prof. Dr. Stefan Böttcher Grundkonzepte erlernen Zum Verständnis des von GUI Designern generierten Codes unerlässlich GUI Designer können oft nicht alles z.B. bei Programmierung und Einsatz von eigenen GUI Komponenten Dynamische GUI Erstellung zur Laufzeit möglich z.B. indem Eingabemasken durch Datenbankinhalte bestimmt werden Grundlagen der Programmierung 2 im SS 2008 3 Ereignisse Universität Paderborn Prof. Dr. Stefan Böttcher Programmbedienung mittels Zeigen, Klicken, Draggen, Tippen, Einrahmen,… Benutzer löst Ereignisse aus Ereignisse müssen abgefangen, erkannt, den richtigen Einheiten zugeordnet und von diesen interpretiert werden Grundlagen der Programmierung 2 im SS 2008 4 Swing Universität Paderborn Prof. Dr. Stefan Böttcher Nachfolger des awt (Abstract Window Toolkit) Wählbares Look & Feel (Motif, Windows, Java, ...) Klassen entspr. Graphischen Komponenten Einbinden von Swing-Komponenten durch import javax.swing.*; class Swing1 { public static void main(String[] args) { JFrame frame = new JFrame("Das Programm"); JLabel label = new JLabel("Hello World!"); frame.getContentPane().add(label); Swing1.java frame.setSize(300,100); frame.setVisible(true); } } Grundlagen der Programmierung 2 im SS 2008 5 JFrame und JLabel Universität Paderborn Prof. Dr. Stefan Böttcher import javax.swing.*; public class FirstSwing { public static void main(String[] args) { JFrame frame = new JFrame("Das Programm"); /* JFrame implementiert gerahmte Fenster Titel wird festgelegt beim Erzeugen (Konstruktor), später mit setTitle(…) */ JLabel label = new JLabel("Hello World!"); /* JFrame implementiert Textanzeige Titel wird festgelegt beim Erzeugen (Konstruktor), später mit setText(…) */ frame.getContentPane().add(label); /* JFrame ist eine eine Container-Klasse sie kann andere Swing-Komponenten aufnehmen und anzeigen indem man die Swing-Komponente dem ContentPane des Frames hinzufügt.*/ frame.setSize(300,100); //300x100 Pixel frame.setVisible(true); //Sichtbarkeit }} Grundlagen der Programmierung 2 im SS 2008 6 Beenden ? Grundlagen der Programmierung 2 im SS 2008 Universität Paderborn Prof. Dr. Stefan Böttcher 7 Beenden! Universität Paderborn Prof. Dr. Stefan Böttcher Frame lebt eigenständig weiter (Thread!) bis er beendet wird Swing2.java import javax.swing.*; public class FirstSwing { public static void main(String[] args) { JFrame frame = new JFrame("Das Programm"); JLabel label = new JLabel("Hello World!"); frame.getContentPane().add(label); frame.setSize(300,100); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }} Grundlagen der Programmierung 2 im SS 2008 8 Komponenten Universität Paderborn Prof. Dr. Stefan Böttcher Component: Objekt mit graphischer Repräsentation (AWT und Swing); verschickt und empfängt Events Container: Behälter für andere Components; kann LayoutManager benutzen JComponent: Basisklasse für alle Swing-Komponenten; kann Look and Feel setzen JFrame, JDialog, JApplet: top-level Swing-Container JPanel: eingebetteter Swing-Container JLabel, JTextField, JButton, …: Swing-Komponenten Grundlagen der Programmierung 2 im SS 2008 9 10 Labels erzeugen Universität Paderborn Prof. Dr. Stefan Böttcher 10 Labels erzeugen, Kontrolle durch Textausgabe … JFrame frame = new JFrame("Das Programm"); for (int i=0; i < 10; i++) { frame.getContentPane().add(new JLabel("Label "+(i+1))); System.out.println("Label "+(i+1)+" erzeugt."); } frame.setSize(300,100); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); … Swing3x.java Grundlagen der Programmierung 2 im SS 2008 10 Layouts Universität Paderborn Prof. Dr. Stefan Böttcher „Fehler“: Standardmäßige Platzierung in der Mitte des contentPane Lösung: Umschalten auf „FlowLayout“: import java.awt.*; … JFrame frame = new JFrame("Das Programm"); frame.getContentPane().setLayout (new FlowLayout()); for (int i=0; i < 10; i++) { frame.getContentPane().add(new JLabel("Label "+(i+1))); System.out.println("Label "+(i+1)+" erzeugt."); } frame.setSize(300,100); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); … Swing3.java Grundlagen der Programmierung 2 im SS 2008 11 Layout Manager Universität Paderborn Prof. Dr. Stefan Böttcher Verantwortlich für Dialogelementanordnung Jeder LayoutManager besitzt eigene Platzierungsstrategie Standard-LayoutManager: FlowLayout GridLayout BorderLayout CardLayout GridBagLayout Null-Layout: direkte Angabe der Pixel Grundlagen der Programmierung 2 im SS 2008 12 FlowLayout Universität Paderborn Prof. Dr. Stefan Böttcher Odnet Dialogelemente nebeneinander in einer Zeile an Passen keine weiteren Elemente in eine Zeile: Fahre mit der nächsten Zeile fort Grundlagen der Programmierung 2 im SS 2008 13 Universität Paderborn Prof. Dr. Stefan Böttcher GridLayout Ordnet Dialogelemente in rechteckigem n mal m Gitter an GridBagLayout ist komplexe Erweiterung des GridLayout GridLayout(int rows, int cols) GridLayout(int rows, int cols, int hgap, int vgap) hgap=horizontal gap between components vgap=vertical gap between components rows=number of rows in the grid cols=number of column in the grid Grundlagen der Programmierung 2 im SS 2008 14 Universität Paderborn Prof. Dr. Stefan Böttcher BoxLayout Elemente werden nebeneinander (X_AXIS) oder untereinander (Y_AXIS) angeordnet Größe der Einzelelemente wird respektiert frame.getContentPane().setLayout( new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS)); Y_AXIS Grundlagen der Programmierung 2 im SS 2008 X_AXIS 15 Border Layout Universität Paderborn Prof. Dr. Stefan Böttcher Verteilt Dialogelemente nach auf vier Randbereiche und Mittelbereich des Fensters: NORTH, SOUTH, WEST, EAST, CENTER import javax.swing.*; import java.awt.*; ... JFrame frame = new JFrame("Das Programm"); frame.getContentPane().setLayout (new BorderLayout()); frame.getContentPane().add(new frame.getContentPane().add(new frame.getContentPane().add(new frame.getContentPane().add(new frame.getContentPane().add(new JLabel("Label Süd"), BorderLayout.SOUTH); JLabel("Label Nord"), BorderLayout.NORTH); JButton("Zentrum"), BorderLayout.CENTER); JLabel("West"), BorderLayout.WEST); JLabel("Ost"), BorderLayout.EAST); Grundlagen der Programmierung 2 im SS 2008 16 Eigener Fenstertyp Universität Paderborn Prof. Dr. Stefan Böttcher import java.awt.*; import javax.swing.*; public class Swing4 extends JFrame{ static int fensterNummer = 0; Swing4(String s) { super(s); //JFrame Konstruktor fensterNummer++; //zählt Fenster getContentPane().setLayout(new FlowLayout()); getContentPane().add(new JLabel("Label")); setSize(200,200); setLocation(50*fensterNummer, 50*fensterNummer); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); //beendet Programm BEIDE Fenster } public static void main(String[] args) { new Swing4("Fenster 1"); new Swing4("Fenster 2"); } Swing4.java } Grundlagen der Programmierung 2 im SS 2008 17 Zeichnen Universität Paderborn Prof. Dr. Stefan Böttcher Einbinden einer Zeichenfläche (JPanel) als eigener JPanel-Typ ("MyPanel") getContentPane().add(new MyPanel()); JPanel besitzt paint-Methode, automatischer Aufruf durch Window-Manager sobald nötig: Erster Aufbau des Panels "Aufdecken" eines Teils des Panels Scrollen Größer ziehen Vordefinierte paint-Methode ist leer (zeichnet nichts), überschreiben: public void paint(Graphics g) { g.drawLine(0, 0, 200, 200); g.drawLine(0, 200, 200, 0); } Grundlagen der Programmierung 2 im SS 2008 18 Paint Methode erstellen Universität Paderborn Prof. Dr. Stefan Böttcher import java.awt.*;import javax.swing.*; public class MyFrame extends JFrame{ static int fensterNummer = 0; MyFrame(String s){ super(s); getContentPane().add(new MyPanel()); fensterNummer++; setSize(300,300); setLocation(50*fensterNummer, 50*fensterNummer); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } class MyPanel extends JPanel { public void paint(Graphics g){ g.drawLine(0, 0, 200, 200); g.drawLine(0, 200, 200, 0);} } public static void main(String[] args) { new MyFrame("Fenster 1"); new MyFrame("Fenster 2"); } Swing5.java } Grundlagen der Programmierung 2 im SS 2008 19 Universität Paderborn Prof. Dr. Stefan Böttcher Diagonalen zeichnen "Feststehende" Linien – unabhängig von Fenstergröße Variante: Zeichnen echter Diagonalen g.drawLine (0, 0, getWidth(), getHeight() ); g.drawLine(getWidth(), 0, 0, getHeight() ); Punkt links oben: (0,0) Punkt rechts unten: (getWidth(), getHeight()) Dynamische Linien – Neuzeichnen bei jeder Änderung der Fenstergröße Swing5a.java Grundlagen der Programmierung 2 im SS 2008 20 Klassenhierarchie Universität Paderborn Prof. Dr. Stefan Böttcher Verschiedene Ebenen der Vererbungshierarchie Object (lang) - die allgemeinste Java-Klasse Component (awt) - die eigentlichen GUI-Elemente (Widgets) Container (awt) - Komponenten, die wieder andere Komponenten aufnehmen können Window (awt) - Fenster ohne Rand Frame (awt) - Fenster mit Rand, http://java.sun.com/j2se/5.0/docs/api/ Titel, Menüleiste, veränderbarer Größe JFrame (swing) - Erweiterung der (älteren) Frame-Klasse des awt, die Frames in die JFC-Umgebung einbindet Grundlagen der Programmierung 2 im SS 2008 21 AWT GUI Komponenten Grundlagen der Programmierung 2 im SS 2008 Universität Paderborn Prof. Dr. Stefan Böttcher 22 Universität Paderborn Prof. Dr. Stefan Böttcher Swing Widgets 1 JScrollPane: JPasswordField: Grundlagen der Programmierung 2 im SS 2008 JTextPane: JEditorPane: 23 Swing Widgets 2 Universität Paderborn Prof. Dr. Stefan Böttcher JScrollBar: JProgressBar: JSlider: JComboBox: Grundlagen der Programmierung 2 im SS 2008 24 Swing Widgets 3 JList: Universität Paderborn Prof. Dr. Stefan Böttcher JList mit Grafiken: JMenu: Grundlagen der Programmierung 2 im SS 2008 25 Universität Paderborn Prof. Dr. Stefan Böttcher Swing Widgets 4 JPopupMenu: JTree / JSplitPane: Grundlagen der Programmierung 2 im SS 2008 JSeperator: JTabbedPane: 26 JTabbedPanel Beispiel Universität Paderborn Prof. Dr. Stefan Böttcher … getContentPane().setLayout (new BorderLayout()); JTabbedPane contentPanel= new JTabbedPane(); JPanel panel1 = new JPanel(); JPanel panel2 = new JPanel(); panel1.add(new JLabel("Ich bin Panel 1")); panel2.add(new JLabel("Ich bin Panel 2")); contentPanel.add("Erstes Panel",panel1); contentPanel.add("Zweites Panel",panel2); getContentPane().add(contentPanel); … Grundlagen der Programmierung 2 im SS 2008 27 Beispiel: Zielscheibe (1) Universität Paderborn Prof. Dr. Stefan Böttcher Grundidee: Zeichnen kleiner werdender konzentrischer, gefüllter Kreise mit abwechselnden Farben (schwarz, weiß) Zeichnen eines Kreises: Suchen in Java-Dokumentation Graphics-Objekte können gefüllte Kreise (Ellipsen) zeichnen! Grundlagen der Programmierung 2 im SS 2008 28 Beispiel: Zielscheibe (2) Universität Paderborn Prof. Dr. Stefan Böttcher Kreis um den Punkt (mx, my) mit Radius r fillOval(mx-r, my-r, 2*r, 2*r); Grundlagen der Programmierung 2 im SS 2008 29 Beispiel: Zielscheibe (3) Universität Paderborn Prof. Dr. Stefan Böttcher Idee: Kreis erzeugen, dann drawMe(..) aufrufen mit Füllfarbe und dem Graphics-Object, „in das“ gezeichnet werden soll. Graphik1.java … class Circle { private int x, y; private double r; Circle(int ix, int iy, double ir) { x = ix; y = iy; r = ir; System.out.println("Kreis um ("+x+", "+y+") mit Radius: "+r); } void drawMe (Graphics g, Color c) { g.setColor(c); g.fillOval((int)(x-r), (int)(y-r), (int)(2*r), (int)(2*r)); } }… Grundlagen der Programmierung 2 im SS 2008 30 Beispiel: Zielscheibe (4) Universität Paderborn Prof. Dr. Stefan Böttcher Wiederverwendung der MyFrame-Klasse, sowie einer eigenen Komponente Zeichenfläche Graphik1.java class MyFrame extends JFrame { MyFrame(String s) { ... getContentPane().add(new Zeichenfläche()); ... } class Zeichenfläche extends JPanel { public void paint(Graphics g) { for (int i=10; i>0; i--) { new Circle(150, 150, i*10.0+5.0). drawMe(g, ( i%2==0 ) ? Color.black : Color.white); } if( i%2 == 0 ) //i modulo 2 } {… Color.black} else } {… Color.white} Grundlagen der Programmierung 2 im SS 2008 31 Beispiel: Zielscheibe (5) Universität Paderborn Prof. Dr. Stefan Böttcher Variante, die variable Ringanzahlen zeichnet: class MyFrame extends JFrame { Zeichenfläche z = new Zeichenfläche(); // Objektvariable! public void setAnzahlRinge(int ar) {z.setAnzahlRinge(ar);} MyFrame() { ... } } class Zeichenfläche extends JPanel { int anzahlRinge = 20; Graphik2.java public void setAnzahlRinge(int ar) {anzahlRinge=ar;} public void paint(Graphics g) { for (int i=anzahlRinge; i>0; i--) { new Circle(150, 150, i*anzahlRinge+5.0). drawMe(g, (i%2==0)?Color.black:Color.white); } } } Grundlagen der Programmierung 2 im SS 2008 32 Beispiel: Zielscheibe (6) Universität Paderborn Prof. Dr. Stefan Böttcher Eingabe der Ringzahlen im Hauptprogramm MyFrame f = new MyFrame("Fenster mit Zielscheibe"); while (true) { System.out.print("Wieviele Ringe?"); Graphik2.java f.setAnzahlRinge(in.nextInt()); } Problem: Gezeichnet wird immer erst nach Verdecken, Verschieben, Scrollen, etc... Expliziter Aufruf von paint(...) nicht möglich Lösung: repaint() erzwingt Aufruf von paint(...) zum nächstmöglichen Zeitpunkt! MyFrame f = new MyFrame("Fenster mit Zielscheibe"); while (true) { System.out.print("Wieviele Ringe?"); f.setAnzahlRinge(in.nextInt()); f.repaint(); } Grundlagen der Programmierung 2 im SS 2008 33 Zusammenfassung Universität Paderborn Prof. Dr. Stefan Böttcher Erste Swing Programme JFrame und JLabel Graphische Komponentenhierarchie Überblick über Layout Manager Zeichnen mittels paint() Methode Überblick über Swing Widgets Zielscheibenbeispiel Komplexere Zeichnungen Repaint() Grundlagen der Programmierung 2 im SS 2008 34 Buttons (1) - Ziel Universität Paderborn Prof. Dr. Stefan Böttcher Ziel: Steuerung durch Buttons Textausgabe mit Labeln Anzeigen von Buttons Programmieren der Reaktion auf Buttons Anordnung (Layout) dieser Elemente Grundlagen der Programmierung 2 im SS 2008 35 Buttons (2) - Ablauf Universität Paderborn Prof. Dr. Stefan Böttcher Ablauf 1. Erzeugen einer eigenen Fensterklasse, mit einer Zeichenfläche, diese wiederum mit geeigneter paint-Methode 2. Erstellen des Dialogfensters 3. Anbindung der Aktionen an die Buttons 4. Beeinflussen des Layouts der Dialogbox Entwicklungsschritt 1: Erzeugen einer Fensterklasse und Zeichenfläche, deren paint()-Methode die Zielscheibe zeichnet Zusätzlich: Objektvariablen in Zeichenfläche (Pos. und Anzahl Ringe) Dafür: Get- und Set-Methoden (in Zeichenfläche und MyFrame) Konsequenz: Aufrufe für setxPos(…), setyPos(…) oder setAnzahlRinge(…) müssen die Zielscheibe neu zeichnen. Grundlagen der Programmierung 2 im SS 2008 36 Buttons (3) - myFrame Universität Paderborn Prof. Dr. Stefan Böttcher Klasse myFrame class MyFrame extends JFrame { StrgZielscheibe.java Zeichenfläche z = new Zeichenfläche(); //getpublic public public public public public und set- Methoden void setAnzahlRinge(int ar) {z.setAnzahlRinge(ar); repaint();} int getAnzahlRinge() { return z.getAnzahlRinge();} void setxPos(int x) { z.setxPos(x); repaint();} void setyPos(int y) { z.setyPos(y); repaint();} int getxPos() { return z.getxPos();} int getyPos() { return z.getyPos();} MyFrame(String s) { //Konstruktor super(s); getContentPane().add(z); setSize(300,300); setLocation(350, 250); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); } } Grundlagen der Programmierung 2 im SS 2008 37 Buttons (4) - Zeichenfläche Universität Paderborn Prof. Dr. Stefan Böttcher Klasse Zeichenfläche class Zeichenfläche extends JPanel { StrgZielscheibe.java //get- und set-Methoden private int anzahlRinge = 10; public void setAnzahlRinge(int a) { anzahlRinge = Math.max(a, 0); } public int getAnzahlRinge() { return anzahlRinge; } private int xPos = 150, yPos = 150; public void setxPos(int x) { xPos = public void setyPos(int y) { yPos = public int getxPos() { return xPos; public int getyPos() { return yPos; //Initiale Position x; } y; } } } public void paint(Graphics g) { for (int i=anzahlRinge; i>0; i--) new Circle(xPos, yPos, i*anzahlRinge+5.0). drawMe(g, (i%2==0)?Color.black:Color.white); } } Grundlagen der Programmierung 2 im SS 2008 38 Buttons (5) - Dialogfenster Universität Paderborn Prof. Dr. Stefan Böttcher Dialogfenster MyDialog wird von JDialog abgeleitet Buttons als Objektvariable Buttons und Label dem ContentPane des Dialogfensters hinzufügen class MyDialog extends JDialog StrgZielscheibe.java { JButton blinks = new JButton("Links schieben"); JButton brechts = new JButton("Rechts schieben"); JButton bplus = new JButton("Mehr Ringe"); JButton bminus = new JButton("Weniger Ringe"); JButton bhoch = new JButton("Hoch schieben"); JButton brunter = new JButton("Runter schieben"); ... Buttons bis hier noch unsichtbar Hinzufügen zu einem ContentPane für Sichtbarkeit Label (konstante Texte) direkt erzeugen und dem ContentPane hinzufügen, Referenzen darauf werden nicht gebraucht. Grundlagen der Programmierung 2 im SS 2008 39 Buttons (6) - myDialog Konstrukor von myDialog Universität Paderborn Prof. Dr. Stefan Böttcher StrgZielscheibe.java MyDialog(String s) { getContentPane().setLayout(new FlowLayout()); getContentPane().add( new Label("Verändern Sie die Anzahl der Ringe") ); getContentPane().add(bplus); getContentPane().add(bminus); getContentPane().add( new Label("Verschieben Sie waagerecht")); getContentPane().add(blinks); getContentPane().add(brechts); getContentPane().add( new Label("Verschieben Sie senkrecht")); getContentPane().add(bhoch); getContentPane().add(brunter); setSize(280,250); setTitle(s); setLocation(10,10); setVisible(true); } Grundlagen der Programmierung 2 im SS 2008 40 Buttons (7) - Aktionen • Anbindung der Aktionen an die Buttons Universität Paderborn Prof. Dr. Stefan Böttcher StrgZielscheibe.java • Prinzip: Erzeugen einer Klasse, die das ActionListener-Interface implementiert interface ActionListener { void actionPerformed(ActionEvent e); } • Instanz der ActionListener Klasse wird Button zugeordnet, auf dessen Drücken reagiert werden soll • Bei Buttonklick wird die actionPerformed(...)-Methode der zugeordneten ActionListener-Klasse aufgerufen • Parameter ActionEvent e enthält zusätzliche Daten (z.B. welcher Button, welche Maustasten, etc.) • Methode actionPerformed(…) enthält Aktion, die der Button auslöst • z.B. Aufruf von setAnzahlRinge(...) Grundlagen der Programmierung 2 im SS 2008 41 Buttons (8) - Aktionen Universität Paderborn Prof. Dr. Stefan Böttcher • Button bplus soll Zahl der Ringe im Frame frame um 1 erhöhen: frame.setAnzahlRinge(frame.getAnzahlRinge()+1); • Entspricht folgender actionPerformed-Methode void actionPerformed (ActionEvent e) { frame.setAnzahlRinge(frame.getAnzahlRinge()+1); } • Muss in Klasse enthalten sein, die ActionListener-Interface implementiert class X ... implements ActionListener { ... } • Zuordnung von Objekt x der Klasse X zum Button bplus bplus.addActionListener(x); • Wird Button bplus gedrückt, wird die Methode actionPerformed(..) des Objektes x der Klasse X ausgeführt. Grundlagen der Programmierung 2 im SS 2008 42 Buttons (9) - Aktionen Universität Paderborn Prof. Dr. Stefan Böttcher • Erweiterung: Wird Instanz x vielen Buttons als ActionListener zugeordnet, muss erkennbar sein, welcher Button gedrückt wurde • Idee: Setzen eines Strings ("ActionCommand") beim Button bplus.setActionCommand(“PLUS“); • Abfrage welcher Button gedrückt wurde in der Methode actionPerformed(ActionEvent e) mit Methode e.getActionCommand() liefert String, der mit Button als „ActionCommand“ verbunden wurde if (e.getActionCommand().equals(“PLUS“)) { ... Aktion für den bplus-Button ... } else if (e.getActionCommand().equals(„MINUS“)) ... Implementierung von ActionListener durch das Dialogobjekt selbst class MyDialog extends JDialog implements ActionListener {..} Grundlagen der Programmierung 2 im SS 2008 43 Buttons (10) - actionPerformed Universität Paderborn Prof. Dr. Stefan Böttcher actionPerformed-Methode von MyDialog public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("PLUS")) frame.setAnzahlRinge(frame.getAnzahlRinge()+1); else if (e.getActionCommand().equals("MINUS")) frame.setAnzahlRinge(frame.getAnzahlRinge()-1); else if (e.getActionCommand().equals("LINKS")) frame.setxPos(frame.getxPos()-10); else if (e.getActionCommand().equals("RECHTS")) frame.setxPos(frame.getxPos()+10); else if (e.getActionCommand().equals("HOCH")) frame.setyPos(frame.getyPos()-10); else if (e.getActionCommand().equals("RUNTER")) frame.setyPos(frame.getyPos()+10); } Grundlagen der Programmierung 2 im SS 2008 44 Buttons (11) - Konstruktor von MyDialog Universität Paderborn Prof. Dr. Stefan Böttcher Buttons müssen Objekt selbst als ActionListener zugewiesen werden: bplus.addActionListener(this); bminus.addActionListener(this); ... Buttons müssen zusätzlich ihr „ActionCommand“ zugewiesen werden: bplus.setActionCommand("PLUS"); bminus.setActionCommand("MINUS"); ... actionPerformed()-Methode muss MyFrame kennen, in das gezeichnet werden soll ⇒ Konstruktor von MyDialog bekommt Referenz darauf als Parameter ⇒ MyDialog speichert Referenz auf MyFrame als Objektvariable frame MyDialog(MyFrame f, String s){ frame = f; ... } Grundlagen der Programmierung 2 im SS 2008 45 Buttons (12) – Übersicht 1 Universität Paderborn Prof. Dr. Stefan Böttcher class MyDialog extends JDialog implements ActionListener { JButton blinks = new JButton("Links schieben"); ... JButton brunter = new JButton("Runter schieben"); MyFrame frame; MyDialog(MyFrame f, String s) { getContentPane().add( new Label("Verändern Sie die Anzahl der Ringe") ); getContentPane().add(blinks); ... getContentPane().add(brunter); setSize(280,250); setTitle(s); setVisible(true); blinks.addActionListener(this); blinks.setActionCommand(“LINKS"); ... brunter.addActionListener(this); brunter.setActionCommand("RUNTER"); frame = f; StrgZielscheibe.java } Grundlagen der Programmierung 2 im SS 2008 46 Buttons (13) – Übersicht 2 Universität Paderborn Prof. Dr. Stefan Böttcher public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("PLUS")) frame.setAnzahlRinge(frame.getAnzahlRinge()+1); else ... if (e.getActionCommand().equals("RUNTER")) StrgZielscheibe.java frame.setyPos(frame.getyPos()+10); } } Unschön: Buttons fließen bei Größenänderungen herum Einfache Lösung: Größenänderungen verbieten! Im Konstruktor von MyDialog: setResizable(false); Grundlagen der Programmierung 2 im SS 2008 47 Buttons (14) – LayoutManager Beispiel Universität Paderborn Prof. Dr. Stefan Böttcher Bislang FlowLayout getContentPane().setLayout(new FlowLayout()); Grid Layout setLayout(new GridLayout(3, 3)); aber: alle Felder sind gleich groß! Grundlagen der Programmierung 2 im SS 2008 48 Buttons (14) – Schachtelung von Layouts Universität Paderborn Prof. Dr. Stefan Böttcher Container kann andere Elemente (u.a. auch Container) aufnehmen, einfachster Container: JPanel Je ein JPanel für Ringzahl, Schieben-X, Schieben-Y Pro JPanel jeweils ein Label und zwei Buttons getContentPane().setLayout( new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); JPanel anzahlPanel = new JPanel(new FlowLayout()); anzahlPanel.add(new Label("Verändern Sie die Anzahl der Ringe")); anzahlPanel.add(bplus); anzahlPanel.add(bminus); getContentPane().add(anzahlPanel); JPanel waagerechtPanel = new JPanel(new FlowLayout()); … Grundlagen der Programmierung 2 im SS 2008 49 Buttons (15) – fertig! Universität Paderborn Prof. Dr. Stefan Böttcher StrgZielscheibe2.java Grundlagen der Programmierung 2 im SS 2008 50 Texteingabefelder Universität Paderborn Prof. Dr. Stefan Böttcher Einzeilige Textfelder: JTextField mehrzeilige Textfelder: JTextArea Abfangen von Ereignissen mit ActionListener-Objekten Wiederholung: Anonyme Klassen Klassen, die keinen Namen haben Getrennt von der Klassendefinition können keine Objekte erzeugt werden Für Erzeugung genau eines Objektes dieser Klasse Technik: Kombination von new X(...) und Definition einer Unterklasse {…} Grundlagen der Programmierung 2 im SS 2008 51 Wdh: Anonyme Klassen class X Universität Paderborn Prof. Dr. Stefan Böttcher { public void m() { System.out.println("KLASSE X"); } } class Test { public static void main(String [] args) { X xObject = new X () { public void m() { System.out.println("Anonyme KLASSE"); } }; xObject.m(); AnonymeKlasse.java } } Was wird ausgegeben? new X (): Erzeugen eines neuen Objektes vom Typ X Aber: Überschreibung der Definition von X durch: { public void m() { System.out.println("Anonyme KLASSE");} }; Es entsteht Objekt einer unbenannten anonymen Klasse Grundlagen der Programmierung 2 im SS 2008 52 Programmiertechnik für Listener 1 Universität Paderborn Prof. Dr. Stefan Böttcher Es existieren diverse Ereignistypen XXXEvent: FocusEvent KeyEvent MouseEvent WindowEvent, ... Variante 1: Zu jedem Ereignistyp XXXEvent existiert ein Interface XXXListener das mögliche Ereignisse aufzählt Beispiel WindowEvent: public interface WindowListener extends EventListener { void windowActivated (WindowEvent); void WindowClosed (WindowEvent); void windowClosing (WindowEvent); ... void windowOpened (WindowEvent); } Grundlagen der Programmierung 2 im SS 2008 53 Programmiertechnik für Listener 2 Universität Paderborn Prof. Dr. Stefan Böttcher Grundidee: 1. Bilden einer Klasseninstanz, die dieses Interface erfüllt 2. Verknüpfen dieser Klasseninstanz mit einer GUI-Komponente, die diesen Ereignistyp erzeugt 3. Die entsprechende Methode wird aufgerufen, sobald das zugehörige Ereignis auftritt Beispiel WindowListener: class MyWindowListener implements WindowListener { void windowActivated (WindowEvent) { /* Aktionen beim Aktivieren des Fensters */ } void WindowClosed (WindowEvent) { ... } void windowClosing (WindowEvent) { System.exit(0); } ... void windowOpened (WindowEvent) { ... } } MyWindowListener mwl = new MyWindowListener(); f.addWindowListener(mwl); Grundlagen der Programmierung 2 im SS 2008 // z.B. für "meinen" MyFrame f 54 Programmiertechnik für Listener 3 Universität Paderborn Prof. Dr. Stefan Böttcher Variante 2: Zu jedem Ereignistyp XXXEvent gibt es eine abstrakte Klasse XXXAdapter mit leeren Methodenimplementierungen: public abstract class WindowAdapter implements WindowListener { public void windowActivated (WindowEvent){} public void WindowClosed (WindowEvent) {} ... public void windowOpened (WindowEvent) {} } Reaktion auf nur wenige Methodenaufrufe des Interface: Deklaration einer Unterklasse von XXXAdapter und Überschreibung der benötigten Adapter-Methoden: f.addWindowListener ( new WindowAdapter(){ public void windowClosing (WindowEvent e) {System.exit(0);} } ); Grundlagen der Programmierung 2 im SS 2008 55 Texteingabe Universität Paderborn Prof. Dr. Stefan Böttcher JTextField: einzeiliger, edierbarer Text Ereignisse: ActionEvent (wie bei Button) ausgelöst bei Return einige Methoden (aus der Oberklasse TextComponent): String getText () Textinhalt liefern void setText (String v) Textinhalt setzen void setEditable (boolean e) Editierbarkeit festlegen boolean isEditable () Editierbarkeit überprüfen void select (int start, int end) Definition des selektierten Teilstring void selectAll () Selektion des gesamten Textes Nach Return: Aufruf der Methode actionPerformed() Darin: Zugriff auf die Ereignisquelle mit getSource() Herausholen des vom Benutzer eingegebenen Textes mit getText() Grundlagen der Programmierung 2 im SS 2008 56 Texteingabe - Listener Universität Paderborn Prof. Dr. Stefan Böttcher Beispiel: ActionListener für JTextField: new ActionListener () { public void actionPerformed (ActionEvent e) { str = (JTextField)(e.getSource()).getText(); } } Beispielprogramm: Benutzer tippt Namen ein Abschluss mit RETURN Ausgeben des Namens Beenden der Editierbarkeit Grundlagen der Programmierung 2 im SS 2008 RETURN 57 Texteingabe - Beispielanwendung Universität Paderborn Prof. Dr. Stefan Böttcher JFrame mit JTextfield class Namenseingabe extends JFrame implements ActionListener { JTextField tNamenseingabe = new JTextField("(unbekannt)"); JLabel l1 = new JLabel ("Geben Sie Ihren Namen ein!"); JLabel l2 = new JLabel ("Ich weiß nicht wie Sie heißen."); public void actionPerformed(ActionEvent e) { l2.setText("Sie heißen also "+((JTextField)e.getSource()).getText() ); tNamenseingabe.setEditable(false); } Namenseingabe() { getContentPane().setLayout(new FlowLayout()); getContentPane().add(l1); getContentPane().add(tNamenseingabe); getContentPane().add(l2); tNamenseingabe.addActionListener(this); tNamenseingabe.selectAll(); //Selektiert Eingabe am Anfang setSize(200, 110); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); TextFeld.java } } Grundlagen der Programmierung 2 im SS 2008 58 Eingabe von Zahlen Universität Paderborn Prof. Dr. Stefan Böttcher Eingelesenen Text in eine Zahl konvertieren, Ausnahme abfangen: try { n = new Integer(str).intValue(); } catch (NumberFormatException e) { ... } try { n = Integer.parseInt (str); } catch (NumberFormatException e) { ... } Programmvariante: Eingabe des Alters, Berechnung des Geburtsjahres, Abfangen von Eingabefehlern (keine Zahl, negatives Alter) Grundlagen der Programmierung 2 im SS 2008 59 Beispiel: Zahleneingabe Universität Paderborn Prof. Dr. Stefan Böttcher public void actionPerformed(ActionEvent e) { int iDiesJahr = 2008; String s = ((JTextField)e.getSource()).getText(); int gebJahr = 0; boolean fehler = false; try { gebJahr = iDiesJahr - Integer.parseInt(s); } catch(NumberFormatException n) { fehler = true; } if (fehler) l2.setText("Sie sollten eine Zahl eingeben."); else if (gebJahr > iDiesJahr) l2.setText("Sie sollten eine nicht-negative Zahl eingeben."); else l2.setText("Ihr Geburtsjahr ist "+gebJahr+"."); tAlterseingabe.selectAll(); } TextFeld2.java Grundlagen der Programmierung 2 im SS 2008 60 Beispiel: Zahleneingabe Universität Paderborn Prof. Dr. Stefan Böttcher Variante: aktuelles Jahr durch Systemzeit bestimmen new Date().toString() liefert Datum, Uhrzeit, Zeitzone. Wed Apr 3 12:34:00 CEST 2008 Feste Positionen der einzelnen Angaben! Jahreszahlermittelung durch (new Date().toString()).substring(25) Berechnung des aktuellen Jahres mit int iDiesJahr = Integer.parseInt( (new Date().toString()).substring(25) ); Grundlagen der Programmierung 2 im SS 2008 61 JTextArea Universität Paderborn Prof. Dr. Stefan Böttcher Für mehrzeiligen Text Kein ActionListener, keine Funktion actionPerformed Return in der JTextArea beendet nicht die Eingabe „Fertig-Button“ außerhalb der JTextArea beendet Eingabe Grundlagen der Programmierung 2 im SS 2008 62 Unterschiede JTextArea JTextField Universität Paderborn Prof. Dr. Stefan Böttcher Angabe der Zeilen und Spalten: JTextArea tLebenseingabe = new JTextArea("(Eingabe \nLebenslauf)", 20, 20); Lesen des eingegebenen Textes mittels Button-Event lebenslauf = tLebenseingabe.getText(); Löschen des eingegebenen Textes duch TextArea.java tLebenseingabe.setText(""); Setzen des Focus (Ziel für Tastatureingabe) auf das JTextField tLebenseingabe.requestFocusInWindow(); Definition des Textumbruchsverhaltens bei der Eingabe tLebenseingabe.setLineWrap(true); tLebenseingabe.setWrapStyleWord(true); Grundlagen der Programmierung 2 im SS 2008 63 Scrollbars für JTextArea Universität Paderborn Prof. Dr. Stefan Böttcher Verwalten der Darstellung der JTextArea durch Container JScrollPane JScrollPane scp = new JScrollPane(tLebenseingabe); getContentPane().add(scp); TextArea2.java Grundlagen der Programmierung 2 im SS 2008 64 JComboBox Universität Paderborn Prof. Dr. Stefan Böttcher Alternativen können der JComboBox als String-Array im Konstruktor übergeben werden: String [] name = { "A", "B", "C" }; JComboBox cAuswahl = new JComboBox(name); ComboBoxTest.java Grundlagen der Programmierung 2 im SS 2008 65 JComboBox Events Universität Paderborn Prof. Dr. Stefan Böttcher Auswahl-Komponenten (JComboBox) lösen ActionEvents aus sobald ein Element ausgewählt wird. Mittels actionPerformed kann ein ActionListener darauf reagieren: cAuswahl.addActionListener(this); public void actionPerformed(ActionEvent e) { lErgebnis.setText("Sie nennen Ihr Baby also " + (String)cAuswahl.getSelectedItem()+"."); } Zugriff auf das gewählte Item über den „Index“: cAuswahl.getSelectedIndex() Bei n Alternativen: Wert zwischen 0 und n-1 Ein ItemListener kann unmittelbar auf Selektionsänderung reagieren – nicht erst nach endgültigem Auswählen Grundlagen der Programmierung 2 im SS 2008 66 JComboBox Items Universität Paderborn Prof. Dr. Stefan Böttcher Items können dynamisch hinzugefügt und entfernt werden: cAuswahl.addItem("D"); cAuswahl.removeItem("A"); Auswahlbox kann "editierbar" sein Freie Eingabe von Texten, nicht nur Auswahl aus vordefinierten Items: cAuswahl.setEditable(true); Übernahme der Eingabe mit getSelectedItem() getSelectedItemIndex() wird dann negativ! Grundlagen der Programmierung 2 im SS 2008 67 Menüs Universität Paderborn Prof. Dr. Stefan Böttcher JMenuBar – Leiste am Fensterrand, welche die Menüs aufnimmt JMenu – Einzelnes Menu unter einer Eintragung in der MenuBar JMenuItem – Menüpunkt (MenuItem), der eine Aktion auslöst ActionListener – MenuItems lösen bei Anwahl ActionEvent aus, Items können mit „ActionCommand“ String identifiziert werden Zuweisung von Tastatur-ShortCuts möglich MenuItems können durch setEnabled(false) deaktiviert („ausgegraut“) werden, durch setEnabled(true) aktiviert werden Menuvariante JPopupMenu erscheint „über“ Objekten Hinzufügen von JMenu als JMenuItem führt zu geschachtelten Menüs Grundlagen der Programmierung 2 im SS 2008 68 Menüs - Programmschema Universität Paderborn Prof. Dr. Stefan Böttcher class MyFrame extends JFrame implements ActionListener { private JMenuBar menuBar; private JMenu einMenu; private JMenuItem item1, item2, item3; ... public MyFrame(...) { //Konstruktor menuBar = new JMenuBar(); //Erzeugen der Menüleiste einMenu = new JMenu("Darstellung"); //Erzeugen eines Menüs item1 = new JMenuItem("Item1"); //Erzeugen eines Items “Item1” item1.setActionCommand("item1-text"); //String für Action item1.addActionListener(this); //Anbinden des ActionListeners ... //analog mit item2, item3, ... einMenu.add(item1); //Einfügen ins Menu einMenu.add(item2); einMenu.addSeparator(); //Einfügen eines Trennstrichs ... menuBar.add(einMenu); // Einbinden des Menus in die Menubar setJMenuBar(menuBar); // Anbinden der Menüleiste in den Frame ... } //Ende des Konstruktors MenuTest.java Grundlagen der Programmierung 2 im SS 2008 69 Menüs - Aktionen Universität Paderborn Prof. Dr. Stefan Böttcher public void actionPerformed(ActionEvent e){ //Bei Menuitem Anwahl String c = e.getActionCommand(); //Holen des ActionCommand Strings if (c.equals("item1-text")) { ... //Aktionen des Menuitems 1 } else { ... } //Abfrage weiterer ActionCommand-Strings } A “verbinden” mit B: A → B JFrame JMenuBar JMenu JMenuItem JMenuItem ... JMenuBar → JFrame: setJMenuBar(JMenuBar) JMenu → JMenuBar: JMenuBar.add(JMenu) JMenuItem → JMenu: JMenu.add(JMenuItem) JMenuItem → ActionCommand: JMenuItem.setActionCommand(ActionCommand) JMenuItem → ActionListener: JMenuItem.addActionListener(...); Jmenu ... Grundlagen der Programmierung 2 im SS 2008 70 Menüs - Beispielprogramm Universität Paderborn Prof. Dr. Stefan Böttcher Datei Neu Öffnen Schliessen Ende Bearbeiten Kopieren Ausschneiden Einfügen Suchen Hilfe Über Index Grundlagen der Programmierung 2 im SS 2008 71 Untermenüs Universität Paderborn Prof. Dr. Stefan Böttcher Einbinden von Menus als Items führt zu Untermenüs, etwa ... Hilfe Über Index Identifier Funktionen Konstanten JMenuItem iIndex (Item Index) ersetzen durch JMenu mIndex (Menü Index) dieses konventionell aufbauen und mit mHilfe.add(mIndex) hinzufügen. MenuTest2.java Grundlagen der Programmierung 2 im SS 2008 72 Zusammenfassung Universität Paderborn Prof. Dr. Stefan Böttcher Dialogfenster Aktionen an Buttons anbinden ActionListener ActionCommand Programmiertechnik für Listener Anonyme Klassen Texteingabefelder ComboBoxen und deren Events Menüs und Untermenüs Grundlagen der Programmierung 2 im SS 2008 73