Listentransformationen in Java

Glazed Lists

Markus Demolsky

Tabellen sind aus heutigen GUIs kaum noch wegzudenken. Die Anwendungspalette reicht von einfachen Listendarstellungen bis hin zu komplexen interaktiven Tabellen, bei denen der User direkt in der Tabelle Daten bearbeitet. Sortierung und Filterung zählen dabei schon zu den Grundausstattungen. Die Entwicklung solcher Tabellen ist daher in vielen Fällen nicht trivial und nimmt etwas Zeit bei der Implementierung in Anspruch. Die in diesem Artikel vorgestellte Bibliothek zielt auf eine abstrakte Entwicklung von Tabellen in Swing-Anwendungen ab und nennt sich Glazed Lists.

Bevor ich nun im Detail auf die Technologie eingehe, möchte ich die grundlegenden Konzepte von Tabellen in Swing-Anwendungen anhand eines kurzen Beispiels erläutern. Ein sehr übersichtliches Einführungstutorial zu diesem Thema befindet sich auf der Sun Homepage. Kernobjekt bei Swingtabellen ist die Klasse JTable, welche für die Darstellung von Tabellen zuständig ist und aus einer Menge von Einzelteilen besteht (Abb. 1).

Abb. 1: Die Klasse JTable

Die JTable ist lediglich die Ansicht der Daten, d.h. die Tabelle beinhaltet weder die Daten, noch werden diese von ihr zwischengespeichert. Die Daten von einer Tabelle stammen vom Tabellenmodell: TableModel. Hier wird also das bekannte MVC Pattern angewendet. Das Zusammenspiel zwischen der JTable und dem TableModel wird im Beispiel ersichtlich werden. Jede Spalte repräsentiert genau einen Datentyp, beispielsweise ein Datum, eine Zahl oder einen String, und jede Zelle zeigt wiederum einen Wert an. Dabei kann die Anzeige und das Verhalten einer Spalte mit entsprechenden TableCellRenderer und TableCellEditor angepasst werden. Beispielsweise möchte man für ein Datumsfeld einen Datepicker in der Tabelle einbauen oder für ein Kategoriefeld eine ComboBox.

Ich möchte nun anhand eines einfachen Beispiels die Erstellung von herkömmlichen Swingtabellen demonstrieren. Dabei wird eine Liste von Artikeln angezeigt. Wir benötigen dafür ein TableModel (Listing 1), welches uns die Daten liefert und auch darüber informiert, in welcher Spalte welcher Wert angezeigt wird. Dieses TableModel packen wir dann in eine JTable (Listing 2) und zeigen die Tabelle an.

Listing 1: Tabellenmodell für Artikel

public class ArticleTableModel extends AbstractTableModel {
    private List
articleList = new ArrayList
(); private String[] columnLabels = {"Marke","Bezeichnung","Kategorie"}; public void setArticleList(List
list){ articleList = list; } public int getColumnCount() { return columnLabels.length; } public int getRowCount() { return articleList.size(); } @Override public String getColumnName(int column) { return columnLabels[column]; } public Object getValueAt(int row, int col) { Article a = (Article)articleList.get(row); switch (col) { case 0: return a.getBrand(); case 1: return a.getTitle(); case 2: return a.getCategory(); default: return null; } }
Listing 2: Einfache Artikelliste mit JTable 

List
articleList = new ArrayList
(); articleList.add(new Article("Adidas","Crossover Climacool","Footwear")); articleList.add(new Article("Adidas","Predator Absolute TRX FG","Footwear")); articleList.add(new Article("Nike","Techfit Seamless Climacool","Shorts")); ArticleTableModel myModel = new ArticleTableModel(); myModel.setArticleList(articleList); JTable t = new JTable(myModel); //Place table in a frame JFrame f = new JFrame(); f.setTitle("Einfache Artikelliste mit Glazed Lists"); f.add(new JScrollPane(t), BorderLayout.CENTER); f.pack(); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true);

Tabellen werden üblicherweise mit Filter, Sortierung und weiteren Funktionen versehen. Bei interaktiven Tabellen, in denen dem Anwender die Möglichkeit geboten wird, die Daten direkt in der Tabelle zu bearbeiten, muss auch immer das Tabellenmodell auf den aktuellsten Stand gebracht werden. Die Implementierung solcher Features kann sehr umfangreich werden. Daher wäre eine Bibliothek wünschenswert, welche immer wiederkehrenden Tabellenfunktionen abstrahiert und bereitstellt.

Glazed Lists

Glazed Lists ist eine Open-Source-Bibliothek zur Transformation von Listen in Java und steht bereits in der Version 1.7.0 zur Verfügung. Beim Einsatz mit Maven reicht folgende Dependency, um GlazedLists in eigenen Projekten zu nutzen:

    net.java.dev.glazedlistsglazedlists_java151.7.0

Der Hauptfokus dieser Technologie liegt vor allem auf der Filterung und Sortierung von Daten sowie dem Binding zum Model, d.h. der Entwickler muss sich nicht mehr um das manuelle Update des Models (Liste) kümmern.

Bei Glazed List spielt das EventList Interface eine entscheidende Rolle. Am besten lässt sich eine EventList wie folgt definieren:

ArrayList + Observer Pattern = EventList

Wie zuvor erwähnt, soll ein Deep Binding zwischen Model und der Tabelle geschehen, d.h. sobald etwas in der Tabelle geändert wird, soll auch das Modell geändert werden. Das Observer Pattern eignet sich für diesen Sachverhalt ideal. Zusammen mit der Liste von Daten entsteht die EventList, eine observable Liste. Die EventList erweitert das java.util.List Interface und beinhaltet die Daten, stellt also das Modell für die Tabelle dar. Betrachten wir das erste Beispiel mit unseren Artikeln nochmals und implementieren das Ganze jetzt mit GlazedLists (Listing 3).

Die BasicEventList ist die einfachste Implementierung der EventList und ermöglicht es, die Daten in Form gängiger Listenformen zu übergeben. In unserem Fall fügen wir die Einträge manuell hinzu. Um nun eine Verbindung zwischen der Liste und unserem Domänenobjekt zu erstellen, erzeugen wir über die GlazedLists Factory ein TableFormat. Das TableFormat wird über unsere Domänenklasse, die anzuzeigenden Attribute (propertyNames) und die Bezeichnung der Spalten (columnLabels) informiert. Als letzten Schritt erstellen wir noch eine JTable mit einem EventTableModel, welches sowohl die Artikelliste als auch unser TableFormat bekommt. Ein Vorteil gegenüber der herkömmlichen Lösung ist das Entfallen des zusätzlichen TableModel-Objektes und die bessere Nachvollziehbarkeit dieses Ansatzes.

Listing 3: Einfache Artikelliste mit Glazed Lists
        
EventList
articleList = BasicEventList
(); articleList.add(new Article("Adidas","Crossover Climacool","Footwear")); articleList.add(new Article("Adidas","Predator Absolute TRX FG","Footwear")); articleList.add(new Article("Nike","Techfit Seamless Climacool","Shorts")); // build a JTable String[] propertyNames = {"brand", "title","category"}; String[] columnLabels = {"Marke", "Bezeichnung", "Kategorie"}; TableFormat
tf = GlazedLists.tableFormat(Article.class, propertyNames, columnLabels); JTable t = new JTable(new EventTableModel
(articleList, tf));
Geschrieben von
Markus Demolsky
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.