Layout und Paint Die Layout und Paint Strategie in AWT/Swing Containern Prof. Dr. Nikolaus Wulff
Dynamische Komponenten Häufig kommt es vor, dass Komponenten auf Grund von Ereignissen zu einem Container hinzugefügt werden. Es liegt nahe anschließen container.repaint() aufzurufen, damit sich dieser neu zeichnet. Leider werden die neuen Komponenten trotzdem nicht sichtbar. Abhilfe verschafft eine Größenveränderung des Fenster. Ein unbefriedigende Lösung... Prof. Dr. Nikolaus Wulff Angewandte Informatik 2
paint-method reloaded Wie und wann werden Widgets mit AWT und Swing gezeichnet? Wann und von wem wird der LayoutManager benötigt und gerufen? Es gibt eine Vielzahl von Methoden mit ähnlich klingendem Namen/Bedeutung: paint(graphics g) update(graphics g) repaint() repaint(long tm) validate() invalidate() revalidate() paint... Prof. Dr. Nikolaus Wulff Angewandte Informatik 3
paint und repaint Es gibt system- und anwendungsgenerierte Zeichenbefehle. Falls das AWT ermittelt, dass eine Komponenten (neu)gezeichnet werden muss, so wird vom AWT in einem synchronen Aufruf paint aufgerufen. Entscheidet die Anwendung, dass eine Komponente gezeichnet werden muss, so wird dies durch repaint markiert und ein entsprechendes PaintEvent in die AWTEvent Queue abgesetzt. Das Zeichnen passiert dann anschließend asynchron außerhalb des Anwendungsthread, der die repaint Methode gerufen hat. Prof. Dr. Nikolaus Wulff Angewandte Informatik 4
paint und update Vor dem eigentlichen Zeichen wird update aufgerufen, dieses löscht den Hintergrund der Komponenten und ruft die paint Methode. Beim repaint Befehl kann eine Zeitspanne und ein Rechteckbereich vorgegeben werden. Hieraus wird eine Optimierungstrategie ermittelt: Nur ein Teil der Komponente muss gezeichnet werden. Liegen mehrere PaintEvents zeitlich dicht zusammen in der EventQueue kann daraus ein einziger update Befehl resultieren... Es wird die einhüllende Summe aller markierten Rechteckbereiche gebildet. Prof. Dr. Nikolaus Wulff Angewandte Informatik 5
Heavy- und Lightweight Components Heavy Components basieren auf Resourcen des Betriebsystems, Frames und Dialoge. Leichtgewichtige Komponenten werden mit reinen Java Bordmitteln gezeichnet. Container müssen daher sicherstellen, dass nach dem eigenen paint alle aggregierten Componenten neugezeichnet werden. Wird in Container Klassen die paint Methode überladen, so muss immer super.paint gerufen werden, um diesen Mechanismus nicht zu unterbrechen. Schwergewichtige Komponenten rufen zuerst die Betriebssystemkomponente und dann alle anderen. Prof. Dr. Nikolaus Wulff Angewandte Informatik 6
Zeichnen mit Swing Swing setzt auf das AWT auf verwendet jedoch mit Ausnahme von JApplet, JFrame und JDialiog keine Heavy Components mehr. Zum Optimieren des Zeichnens wird ein RepaintManger eingeführt mit eigenständiger API. Die paint Methode zerfällt in drei Aufrufe: protected void paintcomponent(graphics g) protected void paintborder(graphics g) protected void paintchildren(graphics g) Daher muss beim Überladen von paint für Swing Komponenten immer super.paint gerufen werden oder es wird nur paintcomponent überladen. Prof. Dr. Nikolaus Wulff Angewandte Informatik 7
Swing UI Delegates Swing verwendet als View das sogenannte UI Delegate. Sofern dieses UI gesetzt ist ruft die paintcomponent am entsprechenden UI die ui.paintcomponent Methode. In eigenen paintcomponent Methoden sollte daher immer zuerste super.paintcomponent gerufen werden bevor dann der eigene Zeichenalgorithmus erfolgt. Daumenregel: Bei AWT und Swing Klassen nie die super Implementierung der Elternklasse abschalten. Prof. Dr. Nikolaus Wulff Angewandte Informatik 8
Synchrones Paint bei Swing Auch Swing unterscheidet zwischen system- und anwendungsgenerierten Zeichenereignissen. Swing verwenden meist. DoubleBuffering. Es wird zuerst die schwergewichtige Komponente (JFrame oder JDialog) per paint gezeichnet. Anschließend alle leichtgewichtigen AWT Kind Komponenten, bis die erste Swing Komponente gefunden wird. Das Zeichnen dieser und aggregierter Swing Komponenten erfolgt in einem Puffer, der dann am Ende als eine Art Image auf den Bildschirm kommt. => Es sollten nie Swing und AWT Komponenten gemischt werden! Prof. Dr. Nikolaus Wulff Angewandte Informatik 9
Asynchrones Paint bei Swing Die JComponent.repaint Methode wird vom RepaintManager ausgewertet, der per invokelater einen Runnable Zeichenauftrag in die EventQueue stellt. Sobald dieses Runnable startet, ruft es per RepaintManager comp.paintimmediately Nun erfolgt das eigentliche Zeichnen analog zum synchronen Systemaufruf. Bei Swing Komponenten wird die update Methode nie verwendet. Die Rolle der Zeichenoptimierung übernimmt der RepaintManager. Prof. Dr. Nikolaus Wulff Angewandte Informatik 10
validate und invalidate Vor einem repaint eines Containers können alle Komponenten neu justiert werden. Mit der invalidate Methode wird der Container markiert. Dieser markiert rekursiv alle Eltern per this.getparent().invalidate() als invalide. Die validate Methode ruft per dolayout den entsprechenden LayoutManager der Komponente und für alle invaliden Kindkomponenten ein neues Layout zu berechnen. Der Aufruf dieser Methoden ist erforderlich, wenn die Komponente bereits sichtbar ist und verändert, z.b. durch ändern der Schrift oder Hinzufügen von Komponenten. Prof. Dr. Nikolaus Wulff Angewandte Informatik 11
Swing revalidate Swing führt zusätzlich die revalidate Methode ein. Diese ruft rekursiv invalidate bis die oberste RootPane ermittelt wurde. Dies ist meist die JRootPane des JFrame oder JDialogs. Anschließend wird die validate Methode der RootPane gerufen und somit abwärts alle als invalide markierten Komponenten neu justiert. D.h. revalidate entspricht im Wesentlichen der Aufruffolge: container.invalidate(); rootparent.validate(); Prof. Dr. Nikolaus Wulff Angewandte Informatik 12
Paint Demonstrator Eine kleine Anwendung soll das unterschiedliche Verhalten von validate, paint und Co. illustrieren. Der Anwender kann per Add-Operation Buttons zu einem JPanel hinzufügen. Per Clear-Operation werden alle Buttons entfernt. Am Panel selber wird anschließend eine der ausgewählten Methoden repaint, validate, invalidate, revalidate oder update explizit aufgerufen. Dies geschieht in einem entsprechenden ActionHandler per switch-case Konstrukt. Prof. Dr. Nikolaus Wulff Angewandte Informatik 13
Demonstrator ActionHandler public void actionperformed(actionevent evt) { JButton button = (JButton) evt.getsource(); if ("clear".equals(button.gettext())) { contentpanel.removeall(); counter=0; } else { JButton comp = new JButton("" + counter++); contentpanel.add(comp); } Choices choice = getchoice(); switch (choice) { case repaint: contentpanel.repaint(); break; case invalidate: contentpanel.invalidate(); break;... Prof. Dr. Nikolaus Wulff Angewandte Informatik 14
invalidate markiert unsichtbar invalidate markiert den Container zeichnet aber keine der Komponenten neu... Die hinzugefügten Buttons bleiben unsichtbar, bis am Fenster gezogen wird... Prof. Dr. Nikolaus Wulff Angewandte Informatik 15
rekursiver Abstrieg mit validate validate berechnet ein neues Layout für den Container und alle aggregierten Kindkomponenten. Die hinzugefügten Buttons erscheinen, aber mit Umbruch obwohl eine ScrollPane da ist... Prof. Dr. Nikolaus Wulff Angewandte Informatik 16
rekursiver Auf- und Abstieg revalidate ermittelt die RootPane und ruft dann rekursiv validate. Jetzt wird auch die einhüllende ScrollPane informiert... Prof. Dr. Nikolaus Wulff Angewandte Informatik 17
clear ohne repaint Werden alle Buttons per Clear aus dem Container entfernt und anschließend wieder mit revalidate oder validate Neue hinzugefügt, so werden die alten Buttons ohne repaint nicht gelöscht! Prof. Dr. Nikolaus Wulff Angewandte Informatik 18
Zusammenfassung Das Zusammenspiel zwischen paint und LayoutManager ist unter Umständen recht trickreich. Zumal AWT und Swing teilweise auf Betriebssystemresourcen aufsetzen... Es kommt daher vor, dass sich Swing GUI Klassen nicht hundertprozentig so verhalten wie man erwartet, da auch deren Programmierer nur Menschen und fehlbar sind... Es ist daher wichtig, das Verhalten zu testen, möglichst auf verschiedenen Betriebsystemen. Prof. Dr. Nikolaus Wulff Angewandte Informatik 19