5 1 Java Desktop Anwendungen das Problem: Desktop-Anwendungen werden mit Hilfe der Swing- Bibliothek programmiert, aber die Swing-Bibliothek ist riesig und unübersichtlich es gab kein Programmiergerüst für den Aufbau von Anwendungen mit einem Standard Look and Feel unerfahrene Programmierer stehen etwas ratlos vor der Aufgabe: public class YourDesktopApp { public static void main(string[] args) { // Viel Glück! }} das Swing Application stellt einen Programmierrahmen zur Verfügung vereinfacht und strukturiert den Aufbau von Desktop Anwendungen
5 2 Aufgaben des s kümmert sich um den Lebenszyklus einer Applikation launch, initialize, startup, ready, exit, shutdown das Resource Management automatisches Laden von Dateien, Bildern, Icons und Beschriftungen, die von der Spracheinstellung des Betriebssystems abhängig sind i.e. die Anwendung ist multilingual programmiert die Definition von Actions Kombination eines ActionListeners mit einem Mechanismus, der den Zustand von Grafikkomponenten beeinflusst z.b. Steuerung der Selektierbarkeit von Schaltflächen die Definition von Tasks z.b. I/O-Operationen, die asynchron ablaufen sollen das Abspeichern von Session-Informationen und Einstellungen
5 3 Unterstützung für das Swing Application Detailinformationen und Beispiele zum finden Sie z.b. unter http://java.sun.com/developer/ technicalarticles/javase/swingappfr/ Das wird von Java-IDE NetBeans 6.1 unterstützt: Informationen und Downloads zur IDE: http://www.netbeans.org Tutorial: Introduction to the Swing Application http://www.netbeans.org/kb/60/java/guisaf.html#intro
5 4 Beispiel ohne Swing A. F.
5 5 Beispiel mit Swing A. F. getmainframe liefert das Frame-Objekt des Applikationsfensters. show zeigt das übergebene Grafikelement im Content Pane des Applikationsfensters.
5 6 Lebenszyklus einer SAF-Applikation 1. launch muss aufgerufen werden, um den Lebenszyklus zu starten 2. initialize launch ruft die restlichen Methoden des Lebenszyklus auf kann optional überschrieben werden Kommandozeilenparameter auswerten, Initialisierungen ausführen, wie z.b. Datenbanken öffnen etc. 3. startup muss überschrieben werden. Hier werden die Grafikkomponenten des Benutzerschnittstelle erzeugt und angezeigt. Benutzen sie die Annotation @Overrride, damit der Compiler sicherstellen kann, dass Sie die richtige Methode überschreiben!
5 7 Lebenszyklus (2) 4. ready 5. exit kann optional überschrieben werden für schnell ablaufende Aufgaben, die darauf angewiesen sind, dass die GUI sichtbar ist wird normalerweise nicht überschrieben und bei einer SingelFrameApplication automatisch aufgerufen, wenn das Applikationsfenster geschlossen wird exit() prüft, ob ExitListener registriert sind und fragt sie, ob ein exit erlaubt ist. -> Beispiel nächste Seite... 6. shutdown sollte überschrieben werden, wenn Aufräumarbeiten (DB schließen etc.) auszuführen sind.
5 8 Beispiel mit ExitListener muss true zurückgeben, wenn die Anwendung beendet werden darf Hier wird ein ExitListener registriert, der von exit() aufgerufen wird. exit() wird automatisch aufgerufen, wenn man das Anwendungsfenster schließen will. exit() wird explizit durch Druck auf den Button aufgerufen. Die Anwendung wird beendet. Hier kann mann noch ein Tschüss... einfügen. hier kann man aufräumen...
5 9 Resource Management Applikations-Ressourcen Texte, Icons, Farben, Fonts, etc. sollten getrennt vom Programmcode in ResourceBundle- Dateien gespeichert werden so können sie einfacher geändert oder in andere Sprachen übersetzt werden das hilft dabei mit dem Klassen: ResourceManager erzeugt ResourceMap-Objekte ResourceMap ein ResourceMap-Objekt enthält die Ressourcen einer zugeordneten ResourceBundle-Datei Namenskonvention:
5 10 Optionen des Resource management Manuelles Laden von ResourceBundles Aufruf von getcontext() liefert ein ApplicationContext-Objekt Aufruf von getresourcemanager() liefert ein ResourceManager-Objekt Aufruf von getresourcemap(<class>) liefert die ResourceMap für die Klasse <class> siehe nächstes Beispiel... automatisches Resource Injection (nur GUI) das lädt die ResourceBundles und füllt die GUI- Komponenten automatisch automatisches Resource Injection (komplett) das lädt die ResourceBundles, füllt GUI- Komponenten automatisch und initialisiert spezifische Datenfelder in Objekten
5 11 manuelles Resource Management ResourceBundle-Datei: resources/helloworld.properties
5 12 Component Resource Injection automatische Parametrierung der Grafikkomponenten mittels Methode injectcomponents() in ResourceMap Namenskonvention setname-methode bei den GUI-Komponenten benutzen den gleichen Namen für die Ressourcen der Komponente in der Ressource-Datei benutzen.property-name definiert einzelne Komonenten-Properties Beispiel: Dateiinhalt von resources/showtimeapp.properties:
5 13 passendes Code-Beispiel
5 14 Injektion von Feldern in Klassen
5 15 automatische Datenkonvertierung
5 16 Actions eine leistungsfähigere Alternative zum einfachen ActionListener erlaubt die Zuordnung von visuellen Elementen zu einem Ereignis ein Menüeintrag kann z.b. enabled oder disabled sein es muss ein Objekt vom Typ AbstractAction hergestellt werden, das das javax.swing.action-interface implementiert Action erweitert das Interface ActionListener um Methoden, wie getvalue(), setenabled(), etc. Das stellt zur Herstellung solcher Objekte die @Action-Annotation zur Verfügung. @Action markiert und benennt Methoden, die im Action-Objekt implementiert werden sollen. Das erzeugt javax.swing.actionmap- Instanzen für alle Klassen, die @Action-Methoden enthalten. Das unterstützt die Lokalisierung von Action-Elementen, wie Texte, Icons und Mnemonics
5 17 Verhalten von Action-Objekten ein Action-Objekt kann mehreren Components zugeordnet werden Actions = ActionListener + Statussteuerung für die Komponente angezeigter Text, select-status, enabled-status für Tool Bars, Buttons, Menu Items, Text Fields Ablauf beim Aufruf der setaction()-methode bei einer Komponente: die Werte der Felder text und icon werden in die Komponente übertragen, genauso die Information enabled und selected das Action-Objekt wird als ActionListener bei der Komponente registriert immer wenn sich nun ein Feld-Wert der Action ändert, wird der Zustand der Komponente automatisch aktualisiert (z.b. enabled-zustand)
5 18 @Action-Beispiel
5 19 Action Ressourcen Hier passiert sehr viel: Action-Instanzen werden für jede durch @Action markierte Methode erzeugt. Es werden Ressourcen aus resources/resizepanel.properties gelesen. Hier wird eine Action-Instanz einem Button zugeordnet. Text und Icon des Button werden automatisch gesetzt.
5 20 Tasks Tasks sind Background-Threads für zeitaufwändige Aufgaben alles was Zeit dauert und nicht als eigenständiger Thread ausgeführt wird, blockiert den Event Dispatch Thread (EDT) dieser Thread ruft die Event-Handler der Komponenten auf. Während ein Event-Handler läuft, können weitere Events (z.b. Button oder Mouse- Clicks) nicht verarbeitet werden! Tasks sorgen dafür, das der EDT nicht blockiert wird.
5 21 Verwendung von Tasks der einfachste Weg: die Klasse org.jdesktop.applivation.task<t,v> im erweitern und Methoden überschreiben auf jeden Fall: protected T doinbackground() throws Exception läuft im Hintergrund und berechnet ein Resultat T und z.b. auch: protected void succeeded(t result) wird aufgerufen, wenn der Task erfolgreich beendet wurde und mit einem Action-Handler kombinieren, der die Task startet es braucht in der Action nur das Task-Objekt erzeugt zu werden, das startet dann den Background-Thread automatisch. - ein Beispiel...
5 22 Beispiel NetworkTimeRetriever Wie läuft das hier?
5 23 Session-Informationen speichern SingleFrameApplication macht es automatisch! Session State = Fensterkonfiguration = Fenstergröße Anordnung der Fenster auf dem Bildschirm andere graphische Eigenschaften, wie Spaltenbreite etc. wenn man die Klasse Application des benutzt, muss man die Session-Infos selber speichern:
5 24 Local Storage - Objekte speichern Die Session-Speicherung benutzt die -Klasse LocalStorage, die die Klassen XMLEncoder und XMLDecoder nutzt, um Objekte in Dateien zu speichern. Anwendung (ctxt = ApplicationContext-Objekt): LocalStorage ls = ctxt.getlocalstorage(); dann dessen Methoden load und save benutzen: public java.lang.object load(java.lang.string filename) throws java.io.ioexception public void save(java.lang.object bean, java.lang.string filename) throws java.io.ioexception so können z.b. auch Programm-Voreinstellungen gespeichert werden preference files
5 25 Beispiel - ein Telefonbuch passend zu unserem Projekt Den Quelltext dieses Beispiels finden Sie unter der Adresse: http://java.sun.com/ developer/technicalarticles/ javase/swingappfr/ AppDemos.zip