Tabeller

En tabell är en helt ny komponent i Swing. De viktigaste klasserna för tabellhantering är följande (alla tabellklasser utom JTable ligger i paketet javax.swing.table):

TableColumn: Innehåller information om hur en kolumn ritas på skärmen, till exempel max- och minbredd, om användaren får ändra dess storlek samt objekt som används för att rita upp och editera celler.
TableColumnModel: Endast en för hela tabellen, inte en per kolumn. Den hanterar markerade kolumner och innehåller en förteckning över alla kolumner samt även kolumnmarginal.
TableModel: Innehåller framför allt tabellens data, dvs själva innehållet i cellerna. Den hanterar dessutom kolumnrubriker och kolumntyp (dvs vilken klass kolumnens objekt är av) samt antal rader och kolumner.
JTable: Innehåller referenser till modellerna och speglar en del information därifrån. Den hanterar också markeringar och innehåller information om hur tabellen ritas (rutnät, färger, radhöjd osv).

Vi börjar med ett mycket enkelt exempel och bygger sedan på det. Klassen JTable har ett antal konstruktorer där data eller storlek kan anges direkt. I exemplet ges data som en tvådimensionell array av Object, SimpleTable.java.

TableColumn

Vi börjar med en titt på klassen TableColumn. I exemplet nedan manipulerar vi lite med rubriken och bredden, som styrs av fyra properties: maxWidth, minWidth, width och resizable. Klassen har en property headerValue som symboliserar rubriken. Det behöver inte vara en sträng utan kan vara ett objekt vilket som helst. Property identifier används för att identifiera en kolumn, se anropet av getColumn() i exemplet. Sätts den inte explicit har den värdet headerValue. Här är exemplet: TableColumnTest.java.

TableColumnModel

Detta är ett gränssnitt som implementeras av klassen DefaultTableColumnModel. Den senare används av tabeller som inte explicit tilldelats en kolumnmodell. TableColumnModel innehåller en indexerad förteckning över antalet kolumner, men indexet har inget med placeringen på skärmen att göra. I nedanstående exempel ärvs DefaultTableColumnModel och metoden addColumn omdefinierats till att, förutom att lägga till kolumner, sortera dem i bokstavsordning enligt kolumnrubrik.

TableColumnModel innehåller metoder för att till exempel flytta och ta bort kolumner. En intressant metod är getColumnIndexAtX() som talar om vilken kolumn som finns vid en viss pixel, och alltså kan användas för att avgöra vilken kolumn användaren klickat på. Ett TableColumnModelEvent skickas när något hänt med en kolumn, se exemplet. Den hanterar även kolumnmarkeringar och skickar ett ListSelectionEvent när markeringen ändras. Som framgår av exemplet är det bättre att fråga kolumnmodellen efter aktuell markering än att fråga eventet. Lägg märke till metoden ListSelectionEvent.getValueIsAdjusting() som talar om i fall användaren är färdig med en markering.

Property columnMargin syftar på avståndet mellan cellerna, inte på rutnätets bredd.

Och så till sist exemplet: ColumnExample.java.

TableModel

Den viktigaste uppgiften för tabellmodellen är att innehålla och hantera tabellens data. TableModel är ett gränssnitt som implementeras av den abstrakta klassen AbstractTableModel. Denna klass implementerar hela interfacet utom metoderna getColumnCount(), getRowCount() och getValueAt(). I Swings dokumentation rekommenderas man att, för bättre prestanda och flexibilitet, ärva av denna klass och skriva en egen modell istället för att placera tabellens data i ett objekt av DefaultTableModel. TableModel innehåller bland annat även metoderna setValutAt(), som är tom i AbstractTableModel, och isCellEditable() som avgör om en cell kan editeras. Den returnerar alltid false i AbstractTableModell.

AbstractTableModel innehåller stöd för att skicka TableModelEvent när tabellens innehåll förändrats, men vi måste själva skriva anropen av de metoder som skickar eventet. Här är ett litet exempel på en egen modell, MyTableModel.java.

Om vi trots allt bestämmer oss för att inte skriva en egen modell används DefaultTableModel, vilken sparar datat som en Vector av Vectorer. Den omdefinierar isCellEditable(), se ovan, till att alltid returnera true. Dessutom tillför den en massa metoder för att hantera tabellens data, både cellvis, radvis, kolumnvis och som helhet. Dessa metoder skickar dessutom verkligen TableModelEvent när tabellens innehåll förändras.

JTable

JTable är den klass som binder ihop de andra. Den innehåller information om hur tabellen ser ut på skärmen: rutnät, färg på markerade celler, radmarginal, vad som händer när tabellen ändrar storlek osv. Den innehåller också information om radmarkeringar och speglar information om kolumnmarkeringar. Vidare finns det en mängd metoder som hanterar objekt för att editera och visa celler, som handhar markeringar och som hanterar kolumner. De senare delegerar hanteringen till kolumnmodellen.

Till sist ett litet exempel som ökar på avståndet mellan cellerna, tillåter markering av enskilda celler istället för rader och programmatiskt startar editering av en cell när användaren trycker på knappen "edit", JTableTest.java. Exemplet lyssnar även efter TabelModelEvent och TabelColumnModelEvent. Observera att ChangeEvent bara skickas när det sker en ändring av markerade kolumner.

Och mycket mer

Det här var lite av det enklaste för att komma igång med tabeller. Det går att göra mycket mer, till exempel skriva och hantera egna objekt för att visa och editera cellinnehåll. Det går också att skriva egna objekt för att hantera kolumnrubriker och att införa tooltips.