Grafische Benutzungsschnittstellen (GUIs) mit Swing

Größe: px
Ab Seite anzeigen:

Download "Grafische Benutzungsschnittstellen (GUIs) mit Swing"

Transkript

1 Java: Kapitel 7 Grafische Benutzungsschnittstellen (GUIs) mit Swing Programmentwicklung WS 2008/2009 Holger Röder holger.roeder@informatik.uni-stuttgart.de

2 Überblick über Kapitel 7 Die GUI-Bibliotheken in Java: AWT und Swing Beispiel: einfache Swing-Anwendung Swing Komponenten, Container, Fenster Ereignisbehandlung Menüs und Toolbars GUI-Komponenten Model-Delegate-Prinzip Swing und Threads 2

3 AWT Die im JDK enthaltene Grafikbibliothek Abstract Windowing Toolkit (AWT) ermöglicht it Java 1.0 die Erstellung grafischer Oberflächen für Java-Programme. AWT ist leicht verständlich, bringt jedoch einige Nachteile mit sich: AWT nutzt die GUI-Elemente des Betriebssystems somit kein einheitliches Look-and-Feel von Java-Programmen unter verschiedenen Betriebssystemen. Nur eine eingeschränkte Menge von GUI-Elementen steht zur Verfügung (z. B. keine Tabellen, keine Bäume). 3

4 Swing Seit Java 1.2 steht mit Swing eine Alternative zum AWT zur Verfügung. Swing zeichnet die GUI-Komponenten lbst: Swing-Programme hen somit auf allen Plattformen (weitgehend) gleich aus. Dies ermöglicht es auch, das Look-and-Feel eines Swing-Programms zur Laufzeit umzuschalten (pluggable look and feel). Swing verwendet eine Model-Delegate-Architektur zur Trennung von Verarbeitungs- und Präntationslogik. Der ursprüngliche Performance-Nachteil von Swing- gegenüber AWT- Anwendungen spielt heute praktisch keine Rolle mehr. Swing erweitert in vielen Fällen die AWT-Klasn. 4

5 Ein einfacher Beispiel-Dialog Labels (JLabel) Fenster (JFrame) Textfelder (JTextField) Button (JButton) 5

6 Swing-Beispiel (1) public class BeispielDialog extends JFrame { JButton buttonspiegeln = new JButton(); JLabel label1 = new JLabel(); JLabel label2 = new JLabel(); JTextField feldeingabe = new JTextField(); JTextField feldausgabe = new JTextField();... Eigene Fensterklas abgeleitet von JFrame Je GUI-Element ein Attribut 6

7 Swing-Beispiel (2)... public BeispielDialog() { super("beispiel-dialog"); tlayout(null);... Konstruktor label1.ttext("eingabe:"); label1.tbounds(new Rectangle(20, 20, 100, 30)); add(label1);... Komponente wird zum Fenster hinzugefügt Aufruf des Oberklasnkonstruktors tzt Fenstertitel Eigenschaften der GUI- Komponenten werden getzt 7

8 Swing-Beispiel (3) Um Thread-Sicherheit zu gewährleisten, erfolgt die Initialisierung des Fensters in einem paraten Thread Ein Objekt der von JFrame abgeleiteten public static void main(string[] args) { Klas wird instanziiert SwingUtilities.invokeLater(new Runnable() { public void run() { BeispielDialog dialog = new BeispielDialog(); dialog.pack(); dialog.tsize(400, 150); dialog.tlocation(300, 200); dialog.tdefaultclooperation(jframe.exit_on_close); dialog.tvisible(true); );... und sichtbar gemacht... 8

9 Swing-Beispiel (4) Look-and-Feel UIManager.tLookAndFeel( "com.sun.java.swing.plaf.windows.windowslookandfeel"); SwingUtilities.updateComponentTreeUI(this); UIManager.tLookAndFeel( "com.sun.java.swing.plaf.motif.motiflookandfeel"); SwingUtilities.updateComponentTreeUI(this); // Vor JFrame-Instanziierung: JFrame.tDefaultLookAndFeelDecorated(true);... UIManager.tLookAndFeel( "javax.swing.plaf.metal.metallookandfeel"); SwingUtilities.updateComponentTreeUI(this); 9

10 Komponenten und Container Als Komponenten werden in Swing einzelne GUI-Elemente bezeichnet, die über eine bestimmte Art der Darstellung verfügen und auf Ereignis reagieren können. Beispiele: Buttons (JButton), Eingabefelder (JTextField), Labels (JLabel), Tabellen (JTable) Basisklas JComponent Container sind spezielle Komponenten, die ihrerits weitere Komponenten aufnehmen können. Der Container ermöglicht das Hinzufügen und Entfernen von Komponenten und übernimmt die Positionierung der in ihm enthaltenen Komponenten. Beispiele: Panels (JPanel), Toolbars (JToolBar), Scroll- Container (JScrollPane) Schachtelung: JTextField innerhalb eines JScrollPane- Containers 10

11 Top-Level-Container Top-Level-Container sind Container auf oberster Ebene JFrame: Hauptfenster einer Anwendung, typisch mit Rahmen, Systemmenü, Titelleiste, Menüleiste JDialog: zumeist modale Dialogfenster (für Benutzerabfragen, spezifische Programmmeldungen etc.) JWindow: rahmenlo Fenster ohne Menüleiste Die meisten Swing-Anwendungen basieren auf JFrame als Basisklas für das Hauptfenster der Anwendung. 11

12 JFrame Schematischer Aufbau Die Layered Pane enthält (optional) eine Menüleiste und die Content Pane Die Content Pane enthält die GUI- Komponenten (Buttons, Eingabefelder etc.) Datei Bearbeiten Ansicht Hallo Welt OK Frame (JFrame) Root Pane Layered Pane Menü/Content P. Glass Pane Die Glass Pane ist üblicherwei unsichtbar und kann Oberflächenereignis filtern 12

13 JFrame als Basis für eigene Anwendungen Über die Methode add() können GUI-Komponenten zur Content Pane des Hauptfensters hinzugefügt werden. JButton meinbutton = new JButton();... add(meinbutton); // Button wird platziert Häufig verwendete Methoden: ttitle(string) tzt den Fenstertitel tmenubar(menubar) fügt eine Menüleiste hinzu pack() tzt alle Komponenten auf ihre bevorzugte Größe tsize(int, int) tzt Fenstergröße tvisible(boolean) zeigt oder versteckt das Fenster dispo() gibt Ressourcen frei, schließt das Fenster tdefaultclooperation(int) Verhalten beim Schließen des Fensters (JFrame.EXIT_ON_CLOSE beendet das Programm beim Schließen des Fensters 13

14 Layout-Manager Die pixelgenaue Positierung von GUI-Komponenten bringt Nachteile mit sich: bei Größenänderung des Fensters, bei unterschiedlichen Schriftgrößen etc. werden die GUI-Komponenten evtl. nicht korrekt dargestellt. Aus diem Grund übernimmt in Swing ein Layout-Manager die Positionierung der Komponenten innerhalb eines Containers. Verschiedene Layout-Manager sind verfügbar, z. B. FlowLayout: Anordnung nebeneinander in Zeile, evtl. neue Zeile BorderLayout: Anordnung links/rechts/oben/unten und mittig GridLayout: Anordnung in rechteckigem Gitter, alle Zellen haben die gleiche Größe GridBagLayout: ebenfalls Gitteranordnung, Zellen können unterschiedliche Größe haben, Komponenten können sich über mehrere Zellen erstrecken Sonderfall null: kein LayoutManager, pixelgenaue Positionierung Über die Methode tlayout() des Containers kann das entsprechende Layout eingestellt werden. 14

15 Layout-Manager Vergleich // Layout-Manager tzen... add(new JButton("Button 1"), BorderLayout.EAST); add(new JButton("Button 2"), BorderLayout.SOUTH); add(new JButton("Button 3"), BorderLayout.WEST); add(new JButton("Button 4"), BorderLayout.CENTER); add(new JButton("Button 5"), BorderLayout.NORTH); tlayout(new FlowLayout()) tlayout(new BorderLayout()) tlayout(new GridLayout(3, 2)) Zweiter Parameter nur für BorderLayout 15

16 Ereignisbehandlung Die Ereignisbehandlung innerhalb von Swing-Anwendungen erfolgt nach dem Listener-Prinzip : Listener-Objekte (event listener) registrieren sich bei möglichen Ereignisquellen (event sources, z. B. Buttons, Textfelder) Bei Auftreten eines Ereigniss (Mausklick, Tastatureingabe etc.) werden die registrierten Listener-Objekte benachrichtigt. Die Listener-Objekte initiieren die pasnde Reaktion auf das Ereignis. Listener können sich bei beliebig vielen Ereignisquellen registrieren, ebenso können Quellen über beliebig viele registrierte Listener verfügen. 16

17 Ereignisbehandlung nach dem Listener-Prinzip Tritt ein Ereignis ein, kann das Listener-Objekt z. B. eine Methode des JFrame- Unterklasnobjekts aufrufen Listener-Objekt Das Listener-Objekt registriert sich beim Button und wird bei Ereignisn benachrichtigt Ereignis: Mausklick, Tastatureingabe... buttonspiegeln.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { buttonspiegeln_actionperformed(e); Anonymes Listener-Objekt );... private void buttonspiegeln_actionperformed(actionevent e) { StringBuffer eingabe = new StringBuffer(feldEingabe.getText()); eingabe.rever(); feldausgabe.ttext(eingabe.tostring()); Ereignisbehandlung 17

18 Ereignis und Listener-Schnittstellen Swing kennt verschiedene Arten von Ereignisn, die jeweils durch unterschiedliche Ereignisklasn repräntiert werden. Listener- Objekte, die über entsprechende Ereignis benachrichtigt werden, müsn die jeweilige Schnittstelle implementieren. Ereignisklas Beschreibung Listener-Schnittstelle KeyEvent Tastendruck KeyListener MouEvent Mausklick, Betreten/ MouListener Verlasn der Komp. MouMotionEvent Mausbewegung MouMotionListener WindowEvent ActionEvent Fenster geschlosn, verkleinert Aktion ausgelöst (z.b. Button gedrückt) WindowListener ActionListener Die Registrierung der Listener-Objekte erfolgt über entsprechende Registrierungsmethoden, z. B. addmoumotionlistener() 18

19 Menüs Eine Menüleiste ist ein Objekt vom Typ JMenuBar, das dem Hauptfenster über die Methode addjmenubar() hinzugefügt wird. Die Menüs sind Instanzen von JMenu, die einzelnen Menüeinträge Instanzen von JMenuItem. JMenu ist eine Unterklas von JMenuItem: Untermenüs können somit realisiert werden, indem ein JMenu-Objekt anstelle eines JMenuItem- Objekts zu einem Menü hinzugefügt wird. JMenuBar menueleiste = new JMenuBar(); JMenu menuedatei = new JMenu(); JMenu menuebearbeiten = new JMenu(); JMenuItem menueeintragspiegeln = new JMenuItem(); 19

20 Menüs (2) menuedatei.ttext("datei"); menuebearbeiten.ttext("bearbeiten"); menueeintragspiegeln.ttext("spiegeln"); menueeintragspiegeln.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { menueeintragspiegeln_actionperformed(e); Anonymes Listener-Objekt ); menuebearbeiten.add(menueeintragspiegeln); menueleiste.add(menuedatei); menueleiste.add(menuebearbeiten); tjmenubar(menueleiste); Menüleiste zu Fenster hinzufügen Menüeintrag zu Menü hinzufügen Menü zu Menüleiste hinzufügen 20

21 Toolbars Toolbars (Werkzeugleisten) sind Container, die andere Komponenten (z. B. Buttons) neben- oder untereinander gruppieren. Toolbars werden als Objekte vom Typ JToolBar realisiert. JToolBar toolbar = new JToolBar(); JButton toolbarbuttonspiegeln = new JButton("Text spiegeln", new ImageIcon("icon.gif")); 21

22 Toolbars (2) JToolBar toolbar = new JToolBar(); JButton toolbarbuttonspiegeln = new JButton("Text spiegeln", new ImageIcon("icon.gif")); toolbarbuttonspiegeln.addactionlistener(new ActionListener() {...); toolbar.add(toolbarbuttonspiegeln); add(toolbar, BorderLayout.NORTH); Toolbar zum Fenster hinzufügen Inhalte (Komponenten) zur Toolbar hinzufügen Toolbars können standardmäßig vom Benutzer frei an den vier Fensterrändern verankert oder freischwebend positioniert werden. Hierzu muss das Fenster BorderLayout verwenden. Die Toolbar muss am Rand angeordnet werden (z. B. BorderLayout.NORTH), die übrigen Fensterinhalte (innerhalb eines Containers) in der Mitte (BorderLayout.CENTER). 22

23 Funktionalität zusammenfasn: Actions Häufig soll in Swing-Anwendungen die gleiche Aktion auf verschiedenen Wegen (Menü, Toolbar etc.) ausführbar in. Actions erlauben es, die gleiche Funktionalität verschiedenen Komponenten zu hinterlegen, ohne die Funktionalität mehrfach (z. B. als anonyme ActionListener-Objekte) implementieren zu müsn. Die Action verwaltet zentral den Zustand (Text, Icon, Ausgewählt? etc.) für die Komponenten. Gleiche Action hinterlegt: Beschriftungstext und hinterlegte Funktionalität sind einheitlich tenabled(fal) im Action-Objekt: alle Komponenten, die mit der Action verknüpft sind, werden deaktiviert 23

24 Action-Beispiel Die Schnittstelle Action implementiert die Schnittstelle ActionListener und kann für alle Komponenten eingetzt werden, die Action-Events auslön: Menüs, Buttons, Textfelder etc. Die Klas AbstractAction bietet Standardimplementierungen für die in Action definierten Methoden und eignet sich in vielen Fällen als Basisklas für eigene Actions. class SpiegelnAction extends AbstractAction { public SpiegelnAction(String text, Icon icon) { super(text, icon); Oberklasnkonstruktor: tzt Beschriftungstext und Icon public void actionperformed(actionevent e) { StringBuffer eingabe = new StringBuffer(feldEingabe.getText()); eingabe.rever(); feldausgabe.ttext(eingabe.tostring()); Eigene Action- Implementierung Methode wird aufgerufen, wenn ein Action-Event ausgelöst wurde 24

25 Action-Beispiel (2) Action instanziieren final SpiegelnAction spiegelnaction = new SpiegelnAction("Text spiegeln", new ImageIcon("icon.gif")); buttonspiegeln = new JButton(spiegelnAction); add(buttonspiegeln); Action den verschiedenen... Komponenten zuwein menueeintragspiegeln = new JMenuItem(); (Konstruktor, explizite Zuweisung) menueeintragspiegeln.taction(spiegelnaction); menueeintragspiegeln.ticon(null); menuebearbeiten.add(menueeintragspiegeln);... toolbarbuttonspiegeln = new JButton(spiegelnAction); toolbar.add(toolbarbuttonspiegeln); 25

26 Zustand in Actions Actions können verschiedene Zustandsattribute verwalten. Über die Methode putvalue(string schluesl, Object o) kann ein Attribut getzt werden, getvalue(string schluesl) liefert das Attribut zurück. Schlüsl Beschreibung Angewendet auf ACCELERATOR_KEY Tastenkombination Menü-Einträge NAME Beschriftung Buttons, Checkboxen, Radiobuttons, Menü- Einträge SHORT_DESCRIPTION ToolTip-Text Buttons, Checkboxen, Radiobuttons SMALL_ICON Icon Buttons, Menü-Einträge (siehe putvalue(small_icon, new ImageIcon("ende.gif")); 26

27 Meldungen mit JOptionPane JOptionPane bietet statische Methoden zur Anzeige typischer modaler Programmmeldungen (Meldung, Nachfragen etc.) JOptionPane.showMessageDialog(null, "Text wurde gespiegelt", "Meldung", JOptionPane.INFORMATION_MESSAGE); if (JOptionPane.showConfirmDialog(null, "Soll der Text gespiegelt werden?", "Frage", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {... 27

28 Übersicht: Swing-GUI-Komponenten (Auszug) javax.swing.jcomponent AbstractButton JMenuItem JLabel JMenu JToggleButton JToolTip JRadioButton JPanel JButton JCheckBox JOptionPane JTextComponent JEditorPane JScrollPane JTextField JTabbedPane JTextArea JTable JTree 28

29 JPanel Ein JPanel-Objekt ist ein (meist) unsichtbarer Container, der in andere Container eingebettet wird. Jedes JPanel-Objekt verfügt über einen Layout-Manager (Standard: FlowLayout), der die enthaltenen Komponenten anordnet. Komplexe Dialoge bestehen häufig aus geschachtelten JPanel- Containern. JFrame mit Layout-Manager GridLayout(2, 1) JPanel mit Layout-Manager BorderLayout() JPanel mit Layout-Manager FlowLayout() 29

30 JTabbedPane Mehrere Registerkarten (Tabs) in einem Fenster können mit der Klas JTabbedPane dargestellt werden. Jede Registerkarte (typisch JPanel-Objekte) kann eigene GUI- Komponenten beinhalten. Über eine am Rand liegende Registerleiste kann zwischen den einzelnen Registerkarten umgeschaltet werden. JTabbedPane tabbedpane = new JTabbedPane( JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); JPanel tab1 = new JPanel(); tab1.add(new JLabel("Eingabe auf Registerkarte 1")); tab1.add(new JTextField(10)); tab1.add(new JButton("Auswerten")); JPanel tab2 = new JPanel();... tabbedpane.addtab("eins", tab1); tabbedpane.addtab("zwei", tab2); add(tabbedpane); Überladener Konstruktor von JTabbedPane: Registerleiste oben positionieren, ggf. scrollen Registerkarten hinzufügen Für jede Registerkarte ein eigenes JPanel-Objekt erzeugen und füllen 30

31 JLabel, JTextField Für Beschriftungen (optional mit Icon) können JLabel-Komponenten verwendet werden. JLabel label = new JLabel("Label mit Icon", new ImageIcon("icon.jpg"), SwingConstants.RIGHT); Icon als.jpg JTextField stellt ein einfaches Eingabefeld dar: JTextField text = new JTextField("Hier steht Text.");... String s = text.gettext(); Text des Textfelds auslen Zur Eingabe von Passwörtern existiert mit JPasswordField eine Spezialisierung von JTextField. 31

32 JButton, JCheckBox Die Klas JButton stellt mit Text oder einem Icon beschriftete Buttons dar. JButton button = new JButton("Drück mich!", new ImageIcon("C:/pe/icon.gif")); button.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) {... // Ereignisbehandlung ); Ereignisbehandlung nach dem Listener-Prinzip: anonymes Listener-Objekt registriert sich beim Button JCheckBox repräntiert Checkboxen. JCheckBox checkbox1 = new JCheckBox("Auswahlbox"); JCheckBox checkbox2 = new JCheckBox("Auswahlbox, true);... if (checkbox1.isselected()) { checkbox2.tselected(fal); Auswahl abfragen, Auswahl tzen 32

33 JRadioButton JRadioButton ähnelt JCheckBox und stellt Radiobuttons dar. Mehrere Radiobuttons können zu einer ButtonGroup gruppiert werden: in einer Gruppe kann stets nur ein Radiobutton aktiv in. JRadioButton button1 = new JRadioButton("Möglichkeit 1", true); JRadioButton button2 = new JRadioButton("Möglichkeit 2"); JRadioButton button3 = new JRadioButton("Möglichkeit 3"); add(button1); add(button2); add(button3); ButtonGroup group = new ButtonGroup(); group.add(button1); group.add(button2); group.add(button3); Logische Gruppierung der Radiobuttons 33

34 Trennung von Daten und Darstellung Die architektonische Trennung der Daten (und Verarbeitungslogik) von der Darstellung der Daten ist ein bewährtes Prinzip des objektorientierten Software-Entwurfs: Saubere Strukturierung des Programmcodes, Entkopplung leichtere Wartung/Erweiterung Darstellung der(lben) Daten auf verschiedene Arten Darstellung 1 Daten a=30% b=50% c=20% Darstellung 2 Auch in Swing-Anwendungen werden Daten und Darstellung getrennt. 20% 50% 30% 34

35 Model-View-Controller (MVC) MVC ist ein Architekturmuster, bei dem Daten (Model), Darstellung (View) und Steuerung (Controller) getrennt werden. a=30% b=50% c=20% Daten und Verarbeitungslogik Model ruft Verarbeitungslogik auf, leitet Änderungen weiter benachrichtigt registrierte Views (Listener) bei Änderungen fragt Daten ab Controller Events (z. B. Benutzereingabe) View (Grafische) Darstellung informiert über notwendige Darstellungsänderung (z. B. durch Textlektion) 35

36 MVC in Swing: Model-Delegate-Prinzip Bei Swing kommt eine vereinfachte Variante von MVC zum Einsatz: das Model-Delegate-Prinzip. Jede Swing-Komponente gliedert sich in zwei Bestandteile: Model: Daten (Zustand) der Komponente UI-Delegate: Grafische Darstellung und Steuerung der Komponente (Darstellung der Daten und Reaktion auf Ereignis) Kombination von View und Controller Model Delegate Controller View 36

37 Model und Delegate bei Swing-Komponenten Bei einfachen Komponenten (Textfelder, Buttons etc.) ist die Aufteilung kaum sichtbar: JTextField feldeingabe = new JTextField(); feldeingabe.ttext("hallo Welt"); Das Modell wird durch Aufruf der Komponentenmethode verändert. Bei UI-Ereignisn (Eintippen/Einfügen von Text) wird das Modell automatisch entsprechend geändert und die Darstellung aktualisiert. Bei Komponenten mit komplexen Inhalten (Listen, Tabellen etc.) wird die Separierung von Model und UI-Delegate klar erkennbar. Zu allen Swing-GUI-Komponenten existieren pasnde Schnittstellen, die die Implementierung eigener Modellklasn erlauben. Häufig enthält das JDK auch Standard-Implementierungen dier Schnittstellen. GUI-Komponente Model Interface Standard-Impl. JButton ButtonModel DefaultButtonModel JTextArea JTable Document TableModel PlainDocument DefaultTableModel etc. 37

38 JList Für Listen steht die Klas JList zur Verfügung. Der Inhalt der Liste (Listenmodell) kann in einem Objekt vom Typ DefaultListModel verwaltet werden. Der Zugriff erfolgt wie bei Vector. Bei Änderungen benachrichtigt das Listenmodell die ListBox automatisch, die Darstellung wird aktualisiert. DefaultListModel listmodel = new DefaultListModel(); JList list = new JList(listModel); add(new JScrollPane(list), BorderLayout.SOUTH); JList wird meistens in JScrollPane eingebettet (scrollbare Liste) Listenmodell: ein Object für jede Zeile; tostring() wird für die Anzeige verwendet. public void buttonhinzu_actionperformed(actionevent e) { listmodel.addelement(eingabe.gettext()); 38

39 JComboBox JComboBox repräntiert Comboboxen (Kombinationen aus Eingabefeld und Liste). JComboBox combobox1 = new JComboBox(); combobox1.additem("rote Auswahl"); combobox1.additem("gelbe Auswahl"); combobox1.additem("blaue Auswahl"); add(combobox1); JComboBox combobox2 = new JComboBox(); combobox2.additem("rote Auswahl"); combobox2.additem("gelbe Auswahl"); combobox2.additem("blaue Auswahl"); combobox2.teditable(true); add(combobox2); Nur vorgegebene Auswahlmöglichkeiten Vorgegebene Auswahlmöglichkeiten und freie Eingabemöglichkeit Als Auswahlmöglichkeiten können beliebige Objects angegeben werden; tostring() wird für die Anzeige verwendet. 39

40 JTable Mit JTable steht eine leistungsfähige Tabellen-Komponente zur Verfügung. In der einfachen Variante wird der Tabelleninhalt als Array vorgegeben: tlayout(new BorderLayout(5, 5)); String[][] inhalt = { { "Audi", "A3 1,9 TDI", "S-HD 3273", { "Mercedes", "CLK 200 K", "ES-XA 177",... ; String[] spalten = { "Hersteller", "Modell", "Kennzeichen" ; JTable table = new JTable(inhalt, spalten); add(new JLabel("Fuhrpark:"), BorderLayout.NORTH); add(new JScrollPane(table), BorderLayout.CENTER); Einbettung in JScrollPane Eigene Tabellen- und Spaltenmodelle ermöglichen den Umgang mit komplexen Daten und bieten mehr Kontrolle über Aufbau und Darstellung der Tabelle. Tabelleninhalt und Spaltenbeschriftungen 40

41 Eigene Tabellenmodelle: TableModel Eigene Tabellenmodelle müsn die Schnittstelle TableModel implementieren. Die Klas DefaultTableModel bietet Standardimplementierungen für die in TableModel definierten Methoden und eignet sich in vielen Fällen als Basisklas für eigene Tabellenmodelle. In TableModel definierte Methoden, die oft überlagert werden: getrowcount(), getcolumncount() liefern die Zahl der Zeilen/Spalten in der Tabelle zurück getvalueat(zeile, spalte) liefert den Inhalt der angegebenen Tabellenzelle zurück getcolumnname(spalte) liefert die Bezeichnung der angegebenen Spalte zurück Wenn sich die Tabellendaten oder die Tabellenstruktur (Spalten etc.) des Tabellenmodells ändern, müsn die JTable-Objekte benachrichtigt werden, damit die Tabellen neu gezeichnet werden: firetabledatachanged(); // Daten/Zeilenzahl geändert firetablestructurechanged(); // Struktur geändert 41

42 Beispiel: Quadratzahlen-Tabelle Tabelle, die eine beliebig wählbare Zahl von Quadratzahlen darstellt Nur wenige Tabellenzellen sind sinnvoll gefüllt Tabelleninhalt ist dynamisch: bei Angabe einer anderen Obergrenze muss die Tabelle neu gezeichnet werden. Benutzer kann Obergrenze der Quadratzahlen lbst wählen 42

43 Tabellenmodell für Quadratzahlen-Tabelle (1) class QuadratzahlenTableModel extends DefaultTableModel { private int max; public EinmaleinsTableModel(int n) { max = n; public int getrowcount() { return max; public int getcolumncount() { return max; public Object getvalueat(int row, int column) { if (row == column) { return String.valueOf((row + 1) * (column + 1)); el { return "-"; public String getcolumnname(int column) { return String.valueOf(column + 1); public void tmax(int n) { max = n; firetablestructurechanged(); Eigene TableModel- Implementierung auf Basis von DefaultTableModel Benachrichtigt JTable- Objekte, dass sich die Struktur der Tabelle (Spaltenzahl) geändert hat und die Tabelle neu gezeichnet werden muss Eigene sinnvolle Implementierung der vorgegebenen Methoden liefert Quadratzahlen 43

44 Tabellenmodell für Quadratzahlen-Tabelle (2)... final QuadratzahlenTableModel modell = new QuadratzahlenTableModel(10); Eigenes Tabellenmodell JTable tabelle = new JTable(modell); wird an JTableadd(new JScrollPane(tabelle)); Konstruktor übergeben... buttonmax.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { int max = Integer.parInt(feldMax.getText()); modell.tmax(max); );... Modell wird geändert; Modell sorgt für Aktualisierung der Darstellung Neben Tabellenmodellen können auf ähnliche Wei auch eigene Spaltenmodelle (Schnittstelle TableColumnModel) und eigene Zellen- Renderer (z. B. für farbige Tabellenzellen; Schnittstelle TableCellRenderer) implementiert werden. 44

45 Swing und Threads Swing-Anwendungen bestehen typisch aus drei Arten von Threads: Die Anwendung startet im Initial Thread. Im Event Dispatch Thread findet die Ereignisbehandlung der Swing-Oberfläche statt. Langlaufende Tätigkeiten werden als Hintergrund-Tasks in Worker Threads ausgeführt. Um Synchronisationsprobleme zu vermeiden, gilt: Sobald eine Swing- Komponente erstmalig dargestellt wird, sollten Zugriffe (Abfragen, Manipulationen etc.) darauf nur innerhalb des Event Dispatch Threads erfolgen! public static void main(string[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { MeinDialog dialog = new MeinDialog(); dialog.tvisible(true); ); Sauberer Start von Swing- Anwendungen: Im Initial Thread (main-methode) wird über invokelater() und ein entsprechendes Runnable-Objekt dafür gesorgt, dass die Swing- Oberfläche erst im EDT erzeugt wird. 45

46 Arbeiten im Hintergrund: SwingWorker Wenn langlaufende Tätigkeiten im EDT ausgeführt werden, ist die Swing-Oberfläche während der Ausführung blockiert. Entsprechende Arbeiten sollten deshalb an asynchrone Hintergrund- Tasks ausgelagert werden. Hierzu dient die abstrakte Klas SwingWorker. SwingWorker<T, V> ist zweifach typisiert: T ist der Ergebnistyp des Threads, V der Typ möglicher Zwischenergebnis. Die Methode T doinbackground() wird in einem eigenen Thread ausgeführt: hier findet die eigentliche (langlaufende) Tätigkeit statt. Die Swing-Oberfläche ist nicht blockiert, da Ereignis weiterhin vom EDT verarbeitet werden können. Die Methode void done() wird im EDT aufgerufen, sobald die Tätigkeit beendet ist: hier kann das Ergebnis mit get() abgerufen und z. B. durch Zugriff auf Swing-Komponenten gefahrlos dargestellt werden. Weitere Möglichkeiten von SwingWorker: 46

47 SwingWorker-Beispiel class DirSizeWorker extends SwingWorker<Long, Void> { protected String dir; public DirSizeWorker(String dir) { this.dir = dir; protected long count(file f) { long size = 0; if (f.isfile()) size = f.length(); el if (f.isdirectory()) { Langlaufende Methode (berechnet rekursiv Verzeichnisgröße) for (File c : f.listfiles()) { size += count(c); return size; protected Long doinbackground() throws Exception { return count(new File(dir)); protected void done() { try { labelsize.ttext( String.format("Größe: %d Bytes%n", get())); catch (Exception exception) { DirSizeWorker worker = new DirSizeWorker(textDir.getText()); worker.execute(); Eigene SwingWorker- Implementierung: Ergebnistyp Long Wird in eigenem Thread ausgeführt, liefert Verzeichnisgröße als Ergebnis Wird im EDT ausgeführt, sobald das Ergebnis vorliegt Ergebnis abrufen, in Swing- Oberfläche darstellen Worker-Objekt erzeugen und ausführen (z.b. innerhalb einer actionperformed()-methode) 47