Java:
package test;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.plaf.UIResource;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class TextWrap extends JFrame {
private static final long serialVersionUID = 1L;
private List<TableData> data = new ArrayList<>();
private JScrollPane scrollPane;
private JTable table;
private MyTableModel tableModel;
private int txtSize = 14;
public static void main(String[] args) {
new TextWrap();
}
public TextWrap() {
data.add(new TableData("event 1 ", "Hier kann eine sich über mehrere Zeilen erstreckende Beschreibung erfolgen"));
data.add(new TableData("event 2 ", "Hier kann eine sich über mehrere Zeilen erstreckende Beschreibung erfolgen"));
data.add(new TableData("event 3 ", "Hier kann eine sich über mehrere Zeilen erstreckende Beschreibung erfolgen"));
data.add(new TableData("event 4 ", "Hier kann eine sich über mehrere Zeilen erstreckende Beschreibung erfolgen"));
data.add(new TableData("event 5 ", "Hier kann eine sich über mehrere Zeilen erstreckende Beschreibung erfolgen"));
this.setTitle("TextWrap-Demo");
this.setSize(800, 320);
this.setLocationByPlatform(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
contentPane.add(getScrollPane(),BorderLayout.CENTER);
JButton btnTxtSize = new JButton("Textgröße ändern");
btnTxtSize.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
txtSize = txtSize == 14 ? 20 : 14;
table.setFont(new Font(Font.DIALOG, Font.PLAIN,txtSize));
updateRowHeight();
}
});
contentPane.add(btnTxtSize,BorderLayout.SOUTH);
this.setContentPane(contentPane);
this.setVisible(true);
}
private JScrollPane getScrollPane() {
if (scrollPane == null) {
scrollPane = new JScrollPane();
scrollPane.setViewportView(getTable());
scrollPane.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
updateRowHeight();
}
});
}
return scrollPane;
}
private JTable getTable() {
if (table == null) {
table = new JTable() ;
table.setFont(new Font(Font.DIALOG, Font.PLAIN,txtSize));
table.setModel(getTableModel());
table.getColumnModel().getColumn(1).setCellRenderer( new MultiLineCellRenderer());
table.getColumnModel().getColumn(1).setCellEditor(new MultiLineCellEditor(table));
}
return table;
}
public MyTableModel getTableModel(){
if(tableModel == null) {
tableModel = new MyTableModel();
}
return tableModel;
}
class MyTableModel extends DefaultTableModel{
String[] colNames = {"Event","Beschreibung"};
@Override
public String getColumnName(int column) {
return this.colNames[column];
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int row, int column) {
return column == 0 ? data.get(row).event : data.get(row).description;
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
@Override
public void setValueAt(Object value, int row, int column) {
if(column == 0)
data.get(row).event = value.toString();
else
data.get(row).description = value.toString();
}
}
public void updateRowHeight() {
int descrColWidth = table.getColumnModel().getColumn(1).getWidth();
JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setFont(table.getFont());
textArea.setSize(new Dimension(descrColWidth,Integer.MAX_VALUE));
for(int r = 0; r < table.getRowCount(); r++) {
textArea.setText(data.get(r).description);
textArea.doLayout();
table.setRowHeight(r,textArea.getPreferredSize().height);
}
}
class TableData{
String event, description;
public TableData(String event, String description) {
super();
this.event = event;
this.description = description;
}
}
class MultiLineCellEditor extends AbstractCellEditor implements UIResource, TableCellEditor {
private static final long serialVersionUID = 1L;
JTable table;
JTextArea editor;
private int row;
DefaultTableCellRenderer defautl = new DefaultTableCellRenderer();
public MultiLineCellEditor(JTable table) {
this.table = table;
this.editor = new JTextArea();
this.editor.setLineWrap(true);
this.editor.setWrapStyleWord(true);
this.editor.setBorder(null);
this.editor.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
table.setRowHeight(row, editor.getPreferredSize().height);
}
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int col) {
this.row = row;
if(value == null) {value = "";}
editor.setFont(table.getFont());
editor.setText(value.toString());
editor.setBorder(defautl.getBorder());
// table.setRowHeight(row, editor.getPreferredSize().height);
return editor;
}
@Override
public Object getCellEditorValue() {
return editor.getText();
}
}
class MultiLineCellRenderer extends JTextArea implements TableCellRenderer{
public MultiLineCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
setFocusable(false);
// setBorder(null);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if(value == null) {value = "";}
setFont(table.getFont());
setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); setText(value.toString());
return this;
};
}
}
Ich habe bereits schon sehr viele Themen im Internet gelesen, die meisten beziehen sich lediglich auf die Darstellung über den Renderer. Grundsätzlich funktioniert mein Beispiel, hat jedoch einige Macken. Die Textgröße soll sich dynamisch ändern lassen, was mit der Schaltfläche im Fenster unten simuliert wird.
Probleme sind z.B. Wenn sich die Größe der Celle ändert und die Scrollleiste der Tabelle eingeblendet wird, dann verliert der Editor den Cursor.
Klickt man nach dem Aufbau der Tabelle in die letzte Zeile, wir diese manchmal kurzzeitig einzeilig dargestellt. Auch variert die Größe um 1-2 zwischen Editor und Renderer um 1-2Pixel, was nicht sehr schön ist.
Das aussehen ist anders als beim DefaultTableCellRenderer, leider lässt dieser keine JTextArea zu.