Also ich hab mir ein beispiel von codeGuru gesaugt und versuche es schon seid ein paar stunden vergeblich auszuführen.
Wäre sehr dankbar, wenn mir jemand weiterhelfen könnte, thx.
Wer sich den ganzen Code hier ersparen will und es lieber direkt runterladen will:
http://www.codeguru.com/java/articles/305.shtml
Klasse Table
Klasse MultiLineTable
Klasse MultinLineCellRenderer
Klasse MultilinebasicTableUI
[Edit by foobar: Returns eingefügt]
Wäre sehr dankbar, wenn mir jemand weiterhelfen könnte, thx.
Wer sich den ganzen Code hier ersparen will und es lieber direkt runterladen will:
http://www.codeguru.com/java/articles/305.shtml
Klasse Table
Code:
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.DefaultListSelectionModel;
public class Table extends JFrame {
public Table(String title) {
super(title);
setSize(600, 400);
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}});
Object[][] data = new Object[][] {{"first row", "\"I was drunk last night, crawled home across the lawn. By accident I put the car key in the door
lock. The house started up. So I figured what the hell, and drove it around the block a few times. I thought I should go park it in the middle of the
freeway and yell at everyone to get off my driveway.\"\n -- Steven Wright"},
{"second row", "The most advantageous, pre-eminent thing thou canst do is not to exhibit nor display thyself within the limits of our galaxy, but
rather depart instantaneously whence thou even now standest and flee to yet another rotten planet in the universe, if thou canst have the good
fortune to find one.\n -- Carlyle"}};
Object[] columns = new Object[] {"first column", "fortune cookie"};
MultiLineTable table = new MultiLineTable(data, columns);
MultiLineCellRenderer multiLineCR = new MultiLineCellRenderer();
table.getColumnModel().getColumn(0).setCellRenderer(multiLineCR);
table.getColumnModel().getColumn(1).setCellRenderer(multiLineCR);
getContentPane().add(new JScrollPane(table));
}
public static void main(String[] args) {
Table table = new Table("Table");
table.show();
}
Klasse MultiLineTable
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.plaf.*;
import javax.swing.text.*;
import java.util.*;
public class MultiLineTable extends JTable {
public MultiLineTable() {
this(null, null, null);
}
public MultiLineTable(TableModel dm) {
this(dm, null, null);
}
public MultiLineTable(TableModel dm, TableColumnModel cm) {
this(dm, cm, null);
}
public MultiLineTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
super(dm,cm,sm);
setUI( new MultiLineBasicTableUI() );
// I know this sucks tremendously, but I was too lazy to find a proper solution. :(
// The problem is, that without this hack, a resize that changes the number of lines in
// the TextArea does not result in the proper resizing of the table, because the
// new width of the column is not available through getWidth until resize is complete.
// Does this make sense? 8-/ Have a look into getRowHeight(int)!
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
revalidate();
}
});
}
public MultiLineTable(int numRows, int numColumns) {
this(new DefaultTableModel(numRows, numColumns));
}
public MultiLineTable(final Vector rowData, final Vector columnNames) {
super( rowData, columnNames );
setUI( new MultiLineBasicTableUI() );
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
revalidate();
}
});
}
public MultiLineTable(final Object[][] rowData, final Object[] columnNames) {
super( rowData, columnNames );
setUI( new MultiLineBasicTableUI() );
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
revalidate();
}
});
}
public int rowAtPoint(Point point) {
int y = point.y;
int rowSpacing = getIntercellSpacing().height;
int rowCount = getRowCount();
int rowHeight = 0;
for (int row=0; row<rowCount; row++) {
rowHeight += getRowHeight(row) + rowSpacing;
if (y < rowHeight) {
return row;
}
}
return -1;
}
public int getHeight(String text, int width) {
FontMetrics fm = getFontMetrics(getFont());
int numLines = 1;
Segment s = new Segment(text.toCharArray(), 0, 0);
s.count = s.array.length;
TabExpander te = new MyTabExpander(fm);
int breaks = getBreakLocation(s, fm, 0, width, te, 0);
while((breaks+s.offset) < s.array.length) {
s.offset += breaks;
s.count = s.array.length - s.offset;
numLines++;
breaks = getBreakLocation(s, fm, 0, width, te, 0);
}
return numLines * fm.getHeight();
}
public int getTabbedTextOffset(Segment s,
FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset,
boolean round) {
int currX = x0;
int nextX = currX;
char[] txt = s.array;
int n = s.offset + s.count;
for (int i = s.offset; i < n; i++) {
if (txt[i] == '\t') {
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX,
startOffset + i - s.offset);
} else {
nextX += metrics.charWidth(' ');
}
} else if (txt[i] == '\n') {
return i - s.offset;
} else if (txt[i] == '\r') {
return i + 1 - s.offset; // kill the newline as well
} else {
nextX += metrics.charWidth(txt[i]);
}
if ((x >= currX) && (x < nextX)) {
// found the hit position... return the appropriate side
if ((round == false) || ((x - currX) < (nextX - x))) {
return i - s.offset;
} else {
return i + 1 - s.offset;
}
}
currX = nextX;
}
return s.count;
}
public int getBreakLocation(Segment s, FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset) {
int index = getTabbedTextOffset(s, metrics, x0, x,
e, startOffset, false);
if ((s.offset+index) < s.array.length) {
for (int i = s.offset + Math.min(index, s.count - 1);
i >= s.offset; i--) {
char ch = s.array[i];
if (Character.isWhitespace(ch)) {
// found whitespace, break here
index = i - s.offset + 1;
break;
}
}
}
return index;
}
class MyTabExpander implements TabExpander {
int tabSize;
public MyTabExpander(FontMetrics metrics) {
tabSize = 5 * metrics.charWidth('m');
}
public float nextTabStop(float x, int offset) {
int ntabs = (int) x / tabSize;
return (ntabs + 1) * tabSize;
}
}
public int getRowHeight() {
System.err.println("getRowHeight() not valid in MultiLineTable");
Thread.dumpStack();
return -1;
}
public int getRowHeight(int row) {
int numCols = getColumnCount();
TableModel tm = getModel();
int fontHeight = getFontMetrics(getFont()).getHeight();
int height = fontHeight;
Enumeration cols = getColumnModel().getColumns();
int i = 0;
while(cols.hasMoreElements()) {
TableColumn col = (TableColumn) cols.nextElement();
TableCellRenderer tcr = col.getCellRenderer();
// without the revalidate hack above, the call th getWidth does not give the
// right value at the right time. Take out the revalidate and uncomment the
// next line to see for your self. If you find a way to do it right, drop me
// a mail please! :)
// System.out.println(col.getWidth());
int colWidth = col.getWidth();
if (tcr instanceof MultiLineCellRenderer) {
height = Math.max(height, getHeight((String)tm.getValueAt(row,i), colWidth));
}
i++;
}
return height;
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle cellFrame;
TableColumn aColumn;
cellFrame = new Rectangle();
// cellFrame.height = getRowHeight() + rowMargin;
// cellFrame.y = row * cellFrame.height;
cellFrame.height = getRowHeight(row) + rowMargin;
cellFrame.y = 0;
for (int i=0; i<row; i++) {
cellFrame.y += getRowHeight(i) + rowMargin;
}
int index = 0;
int columnMargin = getColumnModel().getColumnMargin();
Enumeration enumeration = getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
aColumn = (TableColumn)enumeration.nextElement();
cellFrame.width = aColumn.getWidth() + columnMargin;
if (index == column)
break;
cellFrame.x += cellFrame.width;
index++;
}
if (!includeSpacing) {
Dimension spacing = getIntercellSpacing();
// This is not the same as grow(), it rounds differently.
cellFrame.setBounds(cellFrame.x + spacing.width/2,
cellFrame.y + spacing.height/2,
cellFrame.width - spacing.width,
cellFrame.height - spacing.height);
}
return cellFrame;
}
public void columnSelectionChanged(ListSelectionEvent e) {
repaint();
}
public void valueChanged(ListSelectionEvent e) {
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
repaint();
}
Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
int numColumns = getColumnCount();
int index = firstIndex;
for (int i=0;i<numColumns;i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
index = lastIndex;
for (int i=0;i<numColumns;i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
}
} // MultiLineTable
Klasse MultinLineCellRenderer
Code:
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.border.*;
import java.awt.Component;
import java.awt.Color;
import java.io.Serializable;
public class MultiLineCellRenderer extends JTextArea implements TableCellRenderer, Serializable {
protected static Border noFocusBorder;
private Color unselectedForeground;
private Color unselectedBackground;
public MultiLineCellRenderer() {
super();
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
setBorder(noFocusBorder);
}
public void setForeground(Color c) {
super.setForeground(c);
unselectedForeground = c;
}
public void setBackground(Color c) {
super.setBackground(c);
unselectedBackground = c;
}
public void updateUI() {
super.updateUI();
setForeground(null);
setBackground(null);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
if (isSelected) {
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
}
else {
super.setForeground((unselectedForeground != null) ? unselectedForeground
: table.getForeground());
super.setBackground((unselectedBackground != null) ? unselectedBackground
: table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder( UIManager.getBorder("Table.focusCellHighlightBorder") );
if (table.isCellEditable(row, column)) {
super.setForeground( UIManager.getColor("Table.focusCellForeground") );
super.setBackground( UIManager.getColor("Table.focusCellBackground") );
}
} else {
setBorder(noFocusBorder);
}
setValue(value);
return this;
}
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString());
}
public static class UIResource extends MultiLineCellRenderer implements javax.swing.plaf.UIResource {
}
}
Klasse MultilinebasicTableUI
Code:
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
import java.util.*;
public class MultiLineBasicTableUI extends javax.swing.plaf.basic.BasicTableUI {
public MultiLineBasicTableUI() {
super();
}
private Dimension createTableSize(long width) {
int numCols = table.getColumnCount();
int numRows = table.getRowCount();
TableModel tm = table.getModel();
int fontHeight = table.getFontMetrics(table.getFont()).getHeight();
int[] height = new int[numRows];
for (int i=0; i<numRows; i++) height[i] = fontHeight; // init to font height as minimum
Enumeration cols = table.getColumnModel().getColumns();
int i = 0;
while(cols.hasMoreElements()) {
TableColumn col = (TableColumn) cols.nextElement();
TableCellRenderer tcr = col.getCellRenderer();
int colWidth = col.getWidth();
for (int j=0; j<numRows; j++) {
if (tcr instanceof MultiLineCellRenderer) {
height[j] = Math.max(height[j], ((MultiLineTable)table).getHeight((String)tm.getValueAt(j,i), colWidth));
}
}
i++;
}
int totalMarginWidth = table.getColumnModel().getColumnMargin() * numCols;
// Width is always positive. The call to abs() is a workaround for
// a bug in the 1.1.6 JIT on Windows.
long widthWithMargin = Math.abs(width) + totalMarginWidth;
if (widthWithMargin > Integer.MAX_VALUE) {
widthWithMargin = Integer.MAX_VALUE;
}
int totalHeight = 0;
for (int k=0; k<numRows; k++) totalHeight += height[k];
return new Dimension((int)widthWithMargin, totalHeight + numRows*table.getRowMargin());
}
public Dimension getMinimumSize(JComponent c) {
long width = 0;
Enumeration enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getMinWidth();
}
return createTableSize(width);
}
/**
* Return the preferred size of the table. The preferred height is the
* row height (plus inter-cell spacing) times the number of rows.
* The preferred width is the sum of the preferred widths of each column
* (plus inter-cell spacing).
*/
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createTableSize(width);
}
/**
* Return the maximum size of the table. The maximum height is the
* row height (plus inter-cell spacing) times the number of rows.
* The maximum width is the sum of the maximum widths of each column
* (plus inter-cell spacing).
*/
public Dimension getMaximumSize(JComponent c) {
long width = 0;
Enumeration enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getMaxWidth();
}
return createTableSize(width);
}
public void paint(Graphics g, JComponent c) {
Rectangle oldClipBounds = g.getClipBounds();
Rectangle clipBounds = new Rectangle(oldClipBounds);
int tableWidth = table.getColumnModel().getTotalColumnWidth();
clipBounds.width = Math.min(clipBounds.width, tableWidth);
g.setClip(clipBounds);
// Paint the grid
paintGrid(g);
// Paint the rows
int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
int lastIndex = lastVisibleRow(clipBounds);
int rowMargin = table.getRowMargin();
Rectangle rowRect = new Rectangle(0, 0,
tableWidth,
((MultiLineTable)table).getRowHeight(firstIndex) +
rowMargin);
rowRect.y = 0;
for (int i=0; i<firstIndex; i++) {
rowRect.y += ((MultiLineTable)table).getRowHeight(i) + rowMargin;
}
for (int index = firstIndex; index <= lastIndex; index++) {
// Paint any rows that need to be painted
if (rowRect.intersects(clipBounds)) {
paintRow(g, index);
}
rowRect.y += ((MultiLineTable)table).getRowHeight(index) + rowMargin;
}
g.setClip(oldClipBounds);
}
private void paintGrid(Graphics g) {
g.setColor(table.getGridColor());
if (table.getShowHorizontalLines()) {
paintHorizontalLines(g);
}
if (table.getShowVerticalLines()) {
paintVerticalLines(g);
}
}
/*
* This method paints horizontal lines regardless of whether the
* table is set to paint one automatically.
*/
private void paintHorizontalLines(Graphics g) {
Rectangle r = g.getClipBounds();
Rectangle rect = r;
int firstIndex = table.rowAtPoint(new Point(0, r.y));
int lastIndex = lastVisibleRow(r);
int rowMargin = table.getRowMargin();
int y = - rowMargin;
for (int i=0; i<firstIndex; i++) {
y += ((MultiLineTable)table).getRowHeight(i) + rowMargin;
}
for (int index = firstIndex; index <= lastIndex; index ++) {
y += ((MultiLineTable)table).getRowHeight(index) + rowMargin;
if ((y >= rect.y) && (y <= (rect.y + rect.height))) {
g.drawLine(rect.x, y, rect.x + rect.width - 1, y);
}
}
}
/*
* This method paints vertical lines regardless of whether the
* table is set to paint one automatically.
*/
private void paintVerticalLines(Graphics g) {
Rectangle rect = g.getClipBounds();
int x = 0;
int count = table.getColumnCount();
int horizontalSpacing = table.getIntercellSpacing().width;
for (int index = 0; index <= count; index ++) {
if ((x > 0) && (((x-1) >= rect.x) && ((x-1) <= (rect.x + rect.width)))){
g.drawLine(x - 1, rect.y, x - 1, rect.y + rect.height - 1);
}
if (index < count)
x += ((TableColumn)table.getColumnModel().getColumn(index)).
getWidth() + horizontalSpacing;
}
}
private void paintRow(Graphics g, int row) {
Rectangle rect = g.getClipBounds();
int column = 0;
boolean drawn = false;
int draggedColumnIndex = -1;
Rectangle draggedCellRect = null;
Dimension spacing = table.getIntercellSpacing();
JTableHeader header = table.getTableHeader();
// Set up the cellRect
Rectangle cellRect = new Rectangle();
cellRect.height = ((MultiLineTable)table).getRowHeight(row) + spacing.height;
cellRect.y = 0;
for (int i=0; i<row; i++) {
cellRect.y += ((MultiLineTable)table).getRowHeight(i) + spacing.height;
}
Enumeration enumeration = table.getColumnModel().getColumns();
// Paint the non-dragged table cells first
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
cellRect.width = aColumn.getWidth() + spacing.width;
if (cellRect.intersects(rect)) {
drawn = true;
if ((header == null) || (aColumn != header.getDraggedColumn())) {
paintCell(g, cellRect, row, column);
}
else {
// Paint a gray well in place of the moving column
// This would be unnecessary if we drew the grid more cleverly
g.setColor(table.getParent().getBackground());
g.fillRect(cellRect.x, cellRect.y, cellRect.width, cellRect.height);
draggedCellRect = new Rectangle(cellRect);
draggedColumnIndex = column;
}
}
else {
if (drawn)
// Don't need to iterate through the rest
break;
}
cellRect.x += cellRect.width;
column++;
}
// paint the dragged cell if we are dragging
if (draggedColumnIndex != -1 && draggedCellRect != null) {
draggedCellRect.x += header.getDraggedDistance();
// Fill the background
g.setColor(table.getBackground());
g.fillRect(draggedCellRect.x, draggedCellRect.y,
draggedCellRect.width, draggedCellRect.height);
// paint grid if necessary.
g.setColor(table.getGridColor());
int x1 = draggedCellRect.x;
int y1 = draggedCellRect.y;
int x2 = x1 + draggedCellRect.width - 1;
int y2 = y1 + draggedCellRect.height - 1;
if (table.getShowVerticalLines()) {
// Left
// g.drawLine(x1-1, y1, x1-1, y2);
// Right
g.drawLine(x2, y1, x2, y2);
}
// Bottom
if (table.getShowHorizontalLines()) {
g.drawLine(x1, y2, x2, y2);
}
// Render the cell value
paintCell(g, draggedCellRect, row, draggedColumnIndex);
}
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
// The cellRect is inset by half the intercellSpacing before painted
int spacingHeight = table.getRowMargin();
int spacingWidth = table.getColumnModel().getColumnMargin();
// Round so that when the spacing is 1 the cell does not paint obscure lines.
cellRect.setBounds(cellRect.x + spacingWidth/2, cellRect.y + spacingHeight/2,
cellRect.width - spacingWidth, cellRect.height - spacingHeight);
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null) {
rendererPane.add(component);
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
// Have to restore the cellRect back to it's orginial size
cellRect.setBounds(cellRect.x - spacingWidth/2, cellRect.y - spacingHeight/2,
cellRect.width + spacingWidth, cellRect.height + spacingHeight);
}
private int lastVisibleRow(Rectangle clip) {
int lastIndex = table.rowAtPoint(new Point(0, clip.y + clip.height - 1));
// If the table does not have enough rows to fill the view we'll get -1.
// Replace this with the index of the last row.
if (lastIndex == -1) {
lastIndex = table.getRowCount() -1;
}
return lastIndex;
}
} // MultiLineBasicTableUI
[Edit by foobar: Returns eingefügt]