Mehrzeilige Tabellenzellen
Das Beispiel zeigt eine Tabelle,
in der die mittlere von drei Spalten zur Aufnahme von
mehrzeiligem Text geeignet ist. Dies wird durch das
Einfügen von JTextArea
-Objekten in die
betroffenen Zellen erreicht.
Das graphische Interface
Die Klasse AreaTableBsp
enthält die
Startmethode main()
und erzeugt das GUI der
Anwendung in ihrer Methode initGUI()
, die
im Konstruktor aufgerufen wird.
Hier werden
zuächst zwei String-Arrays, ein eindimensionales
mit den Spaltennamen und ein zweidimensionales mit den
initialen Inhalten der Tabelle erzeugt. Sie werden
verwendet, um das Model vom Typ DefaultTableModel
zu initialisieren. Es wird dem Konstuktor einer JTable
bei deren Erzeugung übergeben. Die Tabelle wird in
eine JScrollPane
gesetzt, die wiederum auf
dem Hauptfenster, einem JFrame
, zentral
dargestellt wird.
Vorher werden der Tabelle
allerdings noch ein Renderer über die Methode setDefaultRenderer()
,
sowie ihrer zweiten Spalte ein CellEditor
hinzugefügt.
import java.awt.Color; import java.awt.Component; import javax.swing.AbstractCellEditor; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellEditor; public class AreaTableBsp { private final int areaRows = 3; private final int areaCols = 20; public AreaTableBsp() { initGUI(); } private void initGUI() { String[] columnNames = { "Spalte 1", "Spalte 2", "Spalte 3" }; String[][] content = { { "Text in Feld 0.0", "Dies ist ein etwas längerer Text in einer JTexArea.", "Text in Feld 0.2" }, { "Text in Feld 1.0", "Text in Feld 1.1", "Text in Feld 1.2" }, { "Text in Feld 2.0", "Text in Feld 2.1", "Text in Feld 2.2" } }; DefaultTableModel model = new DefaultTableModel(content, columnNames); JTable table = new JTable(model); table.setDefaultRenderer(Object.class, new CustomRenderer(areaRows, areaCols)); table.getColumnModel().getColumn(1).setCellEditor(new AreaEditor(areaRows, areaCols)); JScrollPane sp = new JScrollPane(table); JFrame frame = new JFrame(); frame.add(sp); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setTitle("Tabelle mit JTextArea"); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new AreaTableBsp()); } }
CellRenderer und CellEditor
Ein CellRenderer bestimmt die Erscheinung einer unselektierten Tabellenzelle, ein CellEditor die Erscheinung und Funktionalität der selektierten Komponente einer Zelle. Sowohl Editor, als auch Renderer können entweder als Standard der gesamten Tabelle, bzw. einem vorgegebenen Zellinhaltstyp oder aber einzelnen Spalten zugeordnet werden. Zu Demonstrationszwecken wurde hier für Renderer und Editor jeweils eines der beiden Verfahren gewählt.
In Zeile 31 wird, wie oben erwähnt, ein
DefaultRenderer für alle Tabellenzellen bestimmt,
die Objekte vom Typ Object
enthalten.
Hierzu werden der Methode setDefaultRenderer()
zwei Parameter übergeben. Der erste bestimmt den
Inhaltstyp der Zelle in Form eines Class
-Objektes,
für den dieser Renderer gelten soll. Der zweite
Parameter besteht aus dem Renderer-Objekt selbst.
In
Zeile 32 wird für die mittlere Spalte ein
CellEditor definiert.
Sowohl dem Konstruktor des
Renderers, als auch demjenigen des Editors wird jeweils
die Anzahl an Reihen und Spalten für die Erzeugung der
Textarea übergeben.
class CustomRenderer extends DefaultTableCellRenderer { private JTextArea area; private JScrollPane sp; public CustomRenderer(int rows, int cols) { this.area = new JTextArea(rows, cols); this.area.setLineWrap(true); this.area.setWrapStyleWord(true); this.sp = new JScrollPane(area); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (column == 0) { c.setBackground(new Color(255, 230, 200)); } if (column == 2) { c.setBackground(new Color(230, 255, 200)); } if (column == 1) { table.setRowHeight(row, (int) sp.getPreferredSize().getHeight()); area.setText((String) value); c = sp; } return c; } }
Die Renderer-Klasse erweitert hier DefaultTableCellRenderer
und zeigt, wie einerseits eine JTextArea
als mehrzeilige Textkomponente in Tabellenzellen
eingefügt werden kann und andererseits, wie
zusätzlich auch auf andere Zellen zugegriffen und
im Beipiel hier deren Hintergrundfarbe geändert
werden kann.
In der Klasse werden eine JTextArea
und
eine zugehörige JScrollPane
als
private Instanzvariablen deklariert und im Konstruktor
initialisiert. Als einzige Methode der Klasse wird getTableCellRendererComponent()
überschrieben. Sie gibt für jede Tabellenzelle
die Komponente zurück, die dort gerendert werden
soll. Als Parameter werden hierzu alle wesentlichen
Größen übergeben, mit denen die jeweilige
Erscheinung konfiguriert werden kann. U.a. können
die einzelnen Tabellenzellen durch die Idices von Reihe
und Spalte angesprochen werden.
JTable
enthält als Standard in jeder
Zelle ein JLabel
. Es wird durch Aufruf der
Methode der Superklasse als Component
zwischengespeichert und für die erste und dritte
Spalte (Indices 0 und 2) mit einer gänderten
Hintergrundfarbe versehen. Die Die Label der Zellen der
mittleren Spalte (Index 1) werden durch die JScrollPane
mit der geladenen JTextArea
ersetzt. Die
Deklaration der beiden Komponenten als Instanzvariablen
vermeidet hier im Gegensatz zur lokalen Deklaration,
dass jedes Mal bei Aufruf der Methode ein neues Objekt
erzeugt wird.
class AreaEditor extends AbstractCellEditor implements TableCellEditor { private JTextArea area; private JScrollPane sp; public AreaEditor(int rows, int cols) { this.area = new JTextArea(rows, cols); this.area.setLineWrap(true); this.area.setWrapStyleWord(true); this.sp = new JScrollPane(area); } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { area.setText((String) value); return sp; } @Override public Object getCellEditorValue() { return area.getText(); } @Override public boolean stopCellEditing() { return true; } }
Die verwendete Editor-Klasse ist von AbstractCellEditor
abgeleitet und implementiert TableCellEditor
Das Interface wird benötigt, um getTableCellEditorComponent()
bereitzustellen. Ähnlich der Renderer-Methode getTableCellRendererComponent()
gibt diese auch hier die Zellenkomponente zurück.
Da der Editor jedoch lediglich für die mittlere Spalte
benötigt wird, beschränkt sich dies auch auf
das JScrollPane
-Objekt.
Prinzipiell
könnte an dieser Stelle auch von DefaultCellEditor
abgeleitet werden. Da diese Klasse jedoch keinen
parameterlosen Standardkonstruktor anbietet, müsste
dann auf einen von drei überladenen Konstruktoren
zurückgegriffen und diesem entweder ein JTextField
,
eine JCheckBox
oder eine JComboBox
übergeben werden.
Die Zellkomponenten JTextArea
und JScrollPane
werden auch hier als
private Felder deklariert. So kann getCellEditorValue()
auf die Area zugreifen, um deren Wert
zurückzugeben.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.