2011-11-28

Ultimate Swing, Teil 3

Ich habe die Anwendung ein kleines bisschen erweitert. Auf einer dritten Registerkarte können nun Kategorien angezeigt und (später) bearbeitet werden.

Screenshot der Version vom 28.11.2011
Screenshot der Version vom 28.11.2011

TKNotesAndTasks steht übrigens unter der GNU General Public Licence version 3, ist also open source. Das am Ende des Posts verlinkte Archiv enthält wie üblich alle Quelltexte. Ich habe begonnen, die Dateien mit einem Hinweis auf die GPL zu versehen. Und so langsam trudeln auch die ersten Javadoc-Elemente ein.
Smiley

Lassen Sie uns nun nochmals einen Blick auf die Struktur des Programms werfen. Eine einfache Starter-Klasse (Main) ruft Application.boot() auf. Application ist ein Singleton, das korrespondierende Objekt repräsentiert also die Anwendung. Aber: Application enthält keine programmspezifischen Funktionen. Diese sind in einer Klasse enthalten, die das Interface ApplicationCallback implementiert. Eine Instanz dieses Typs wurde in Main erzeugt und an boot() übergeben. ApplicationCallback definiert – das hatte ich bereits geschrieben – Lebenszyklusmethoden, die von Application zu bestimmten Zeiten aufgerufen werden. Seit der ersten Fassung ist eine neue hinzugekommen: preCreateGUI(). Wir werden diese bald benötigen, um Daten zu laden. Dies geschieht quasi-parallel zum Aufbau der Benutzeroberfläche. Hierfür wiederum ist createGUI() zuständig. Lassen Sie uns nun einen Blick auf die entsprechende Implementierung werfen:

  public static synchronized void boot(String[] args, String bundleBaseName,
      ApplicationCallback cb) {
    if (INSTANCE != null) {
      throw new IllegalStateException(
          "boot() must not be called more than once");
    }
    INSTANCE = new Application(args, bundleBaseName, cb);
    Thread t = new Thread(new Runnable() {
      @Override
      public void run() {
        INSTANCE.callback.preCreateGUI(INSTANCE.args);
      }
    });
    t.start();
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        INSTANCE.configureFrame();
        INSTANCE.setVisible(true);
      }
    });
  }

In dieser Version erledigt die Methode boot() drei Aufgaben.

  1. Instantiieren eines Objekts vom Typ Application
  2. Erzeugen und Starten eines Threads, der die Methode preCreateGUI() aufruft
  3. Ausführen der beiden Aufrufe configureFrame() und setVisible()

Und worin liegt der Unterschied zwischen 2) und 3)? Der Event Dispatching Thread wird Sie bei der Arbeit mit Swing noch oft begleiten. In Vorbereitung auf den nächsten Post können Sie sich schon einmal warm googlen.
Smiley

Quelltexte zu TKNotesAndTasks vom 28.11.2011

Frage zur Schuhschachtel

In diesem Post möchte ich kurz auf die Frage eines Lesers antworten. Er (oder sie) möchte wissen, ob man die Schuhschachtel in einem zentralen Verzeichnis ablegen und ohne Kopieraktionen in mehreren Projekten verwenden kann. Grundsätzlich wird dieses Ansinnen durch die Tatsache erschwert, dass sie aufgrund des Paketnamens (com.thomaskuenneth.shoebox) mit dem Rest der Anwendung quasi verwoben ist. Wäre dies nicht der Fall (sagen wir, der Paketname wäre de.thomaskuenneth.shoebox), könnte man ein neues Eclipse-Projekt anlegen und dessen src-Verzeichnis auf den Ordner zeigen lassen, der de.thomaskuenneth.shoebox enthält. Das Projekt wiederum ließe sich problemlos über die Projekteigenschaften einbinden. Alternativ hätte ich die Schuhschachtel natürlich gleich als eigenständiges Projekt anbieten können. Aber das riecht sehr stark nach Framework, und genau das möchte ich eben nicht. Vorschlag: wenn Sie die Schuhschachtel tatsächlich wie ein kleines Framework verwenden möchten, rate ich zu einem kleinen Shellscript, dass meine .zip-Datei auspackt und alle Shoebox-Dateien in das src-Verzeichnis eines eigenen Eclipse-Projekts kopiert. Das können Sie, wie bereits angedeutet, leicht in andere Projekte einhängen.

2011-11-25

Ultimate Swing, Teil 2

Zu Beginn möchte ich mich bei allen, die einen Kommentar hinterlassen haben, herzlich bedanken. Ich freue mich, dass mein Projekt Zuspruch findet und Interesse weckt.
Screenshot TKNotesAndTasks
Screenshot TKNotesAndTasks
Ziel des heutigen Posts ist, Ihnen alle Quelltexte an die Hand zu geben, die Sie benötigen, um das oben gezeigte Fenster zu erzeugen. Die Verteilung der Sourcen wird immer in Gestalt eines .zip-Archivs erfolgen, das das Verzeichnis “src” enthält. Da die meisten IDEs die Quelltexte eines Projekts in Ordnern mit diesem Namen ablegen, ist es am einfachsten, einmal ein neues Projekt anzulegen und später einfach mit jeder “Lieferung” das src-Verzeichnis zu überschreiben. Anschließend ein Clean und Build All. Schon haben Sie eine ablauffähige Anwendung. Lassen Sie uns nun einen Blick auf den Package Explorer (ich verwende Eclipse) werfen.
Screenshot Package Explorer
Screenshot Package Explorer
Ist Ihnen die grundsätzliche Aufteilung in die beiden Pakete com.thomaskuenneth.shoebox und com.thomaskuenneth.notesandtasks aufgefallen? Ich möchte Ihnen kein weiteres Swing-Framework vorschlagen – es gibt einfach schon zu viele. Dennoch ist Wiederverwendung im Sinne der Arbeitserleichterung selbstverständlich ein wichtiges Ziel für jeden Entwickler. Aus diesem Grund lagere ich Kandidaten für die Nutzung in anderen Programmen in das shoebox-Paket aus. Meine Schuhschachtel enthält allerlei Krimskrams, das ich mir bei Bedarf einfach nehme. Eine solche Vorgehensweise möchte ich auch Ihnen ans Herz legen. Aber widerstehen Sie der Versuchung, Bibliotheken zu bauen. Die Zeit, die Sie in die Ausgestaltung einer API stecken, ist besser in Tests investiert - glauben Sie mir.
Lassen Sie uns nun einen Blick auf die Hauptklasse der Anwendung werfen.

package com.thomaskuenneth.notesandtasks;

import com.thomaskuenneth.notesandtasks.controller.MainController;
import com.thomaskuenneth.shoebox.app.Application;

public class Main {

  public static void main(String[] args) {
    Application.boot(args, "com.thomaskuenneth.notesandtasks.messages",
        new MainController());
  }
}
Das riecht – ich sehe Ihren verwunderten Blick – nach Framework. Ich habe Teile des Start- und Beendigungsvorgangs in die Klasse Application ausgelagert, weil ich diese Stück für Stück erweitern kann. Was passiert hier? Ein Objekt des Typs MainController wird, neben den Kommandozeilenargumenten und einem (scheinbaren) Paketnamen, an die statische Methode boot der Klasse Application übergeben.

public class MainController implements ActionListener, ApplicationCallback {
Die Implementierung muss uns an dieser Stelle nicht interessieren – wichtig ist, dass die Klasse das Interface ApplicationCallback implementiert. Das ist (derzeit noch) sehr überschaubar:

package com.thomaskuenneth.shoebox.app;

import javax.swing.JComponent;

public interface ApplicationCallback {

  public JComponent createGUI();
 
  public boolean canShutdown();
}
Die Klasse Application öffnet ein Fenster und stellt einen Komponentenbaum dar, den eine Implementierung der Methode createGUI() liefert. Damit möchte ich diesen Teil meiner losen Serie beschließen. Bitte sehen Sie sich die Klasse Application genauer an. Wenn Sie Fragen oder Anregungen haben, freue ich mich sehr über Ihre Nachricht.
Quelltexte zu TKNotesAndTasks vom 25.11.2011

2011-11-23

Ultimate Swing, Teil 1

Gehen Ihnen die unzähligen Ankündigungen und “Leaks” rund um Android auch irgendwie auf den Wecker? Ich bin ja nun wirklich ein Fan von schönen neuen Dingen, aber zur Zeit habe ich irgendwie das Gefühl, diese Flut ersäuft alles. Deshalb habe ich beschlossen, in nächster Zeit etwas öfter andere Sachen einzustreuen. Zum Beispiel, wie man richtig Software baut. Da trifft es sich gut, dass ich in meinem iX-Artikel Der letzte Tanz Swing quasi in Ruhestand geschickt habe. Genau der richtige Zeitpunkt also, eine App …pardon… Anwendung mit eben dieser Klassenbibliothek zu entwickeln.
Smiley

Mein Ziel ist, ein cooles, zeitgemäßes und grafisch opulentes Programm zu coden, das ohne zusätzliche Frameworks und Bibliotheken auskommt. Swing pur. Ich werde Ihnen zeigen, wie man Swing richtig benutzt. Und wie man seine Anwendung vernünftig schichtet. Falls Sie sich nun fragen, warum jetzt – ich hab Lust dazu. Mein Ziel ist, am Ende alles in einem (letzten?) Buch über Swing zusammenzufassen.

Los geht’s…

Notes and Tasks – Notizen und Aufgaben
Das Programm, das ich im Rahmen dieser losen Serie entwickeln werde, ist eine Cloud-basierte Aufgaben- und Notizverwaltung – das “Backend” ist ein Google-Konto. Aber dazu später mehr. Zunächst – als eine Art Appetithappen – ein Scribble des Anwendungshauptfensters.

Scribble des Anwendungshauptfensters
Scribble des Anwendungshauptfensters

Langweilig? Klar. Ich werde mich jedem Themenkomplex iterativ nähern, das bedeutet, ich werde Ihnen nie eine fertige Version “vorsetzten”, sondern jeweils von einer Basisversion ausgehen und diese sukzessive verbessern und erweitern.

Das Anwendungshauptfenster besteht in seiner ersten Fassung aus zwei Teilen: a) einem Schnelleingabebereich für Aufgaben und Notizen, sowie b) einem Bereich mit zwei Registerkarten (Aufgaben und Notizen). Viel später werden wir das Aussehen der Anwendung so umgestalten, dass die Metapher der Registerkarten stark in den Hintergrund tritt. Aber JTabbedPane ist so angenehm einsetzbar, dass es eine Schande wäre, nicht darauf zu setzen.Die Idee des Schnelleingabebereichs ist, jederzeit etwas erfassen zu können. Einfach drauf los tippen und mit Enter oder Anklicken einer Schaltfläche abschließen. Ob der eingetippte Text zu einer Aufgabe oder aber einer Notiz wird, hängt davon ab, welche Registerkarte aktiv ist. Das mag auf den ersten Blick nicht intuitiv erscheinen. Aber ein Hinweis im leeren Eingabefeld wird dem Anwender einen entsprechenden Fingerzeig geben.

2011-11-04

Tschüs Harmony, und vielen Dank...

http://java.dzone.com/news/apache-harmony-finally
...ich bin gespannt, ob und wenn ja welche Auswirkungen das auf den Rechtsstreit zwischen Google und Oracle hat...