我有一个JTextArea,我用它作为表格的单元格渲染器.在getTableCellRenderercomponent方法中,我有:
setText(getTextForCell());
setSize(table.getColumnModel().getColumn(column).getWidth(), 0);
getUI().getRootView(textArea).setSize(textArea.getWidth(), 0f);
updateSize();
private void updateSize() {
int prefHeight = textArea.getPreferredSize().height;
int currHeight = table.getRowHeight(r);
if (prefHeight > currHeight) {
table.setRowHeight(row, prefHeight);
}
当文本区域使用换行样式字时,它有时会短一行.
如果我从getTableCellRendererComponent外部调用此updateSize方法,那么它可以正常工作.但是对于一个大表,每当列大小调整时调用所有行的更新大小都是不可行的,因为它太慢了,所以我一直试图找到一种方法在行渲染期间进行调整大小.
有一个相关的Java错误(标记为已修复,但它看起来并非如此)http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4446522,但这种解决方法在使用自动换行时似乎不起作用.
任何人都可以提供如何使这项工作正常的替代方案吗?
解决方法:
替代方案正常工作
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
public class AutoWrapInJTable {
public AutoWrapInJTable() {
String[] columnNames = {"TextAreaCellRenderer"};
Object[][] data = {
{"123456789012345678901234567890"},
{"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
TableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model) {
private static final long serialVersionUID = 1L;
@Override
public void doLayout() {
TableColumn col = getColumnModel().getColumn(0);
for (int row = 0; row < getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, 0);
if (c instanceof JTextArea) {
JTextArea a = (JTextArea) c;
int h = getPreferredHeight(a) + getIntercellSpacing().height;
if (getRowHeight(row) != h) {
setRowHeight(row, h);
}
}
}
super.doLayout();
}//http://tips4java.wordpress.com/2008/10/26/text-utilities/
private int getPreferredHeight(JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
};
table.setEnabled(false);
table.setShowGrid(false);
table.setTableHeader(null);
table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane sp = new JScrollPane(table);
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel p = new JPanel(new BorderLayout());
p.add(sp);
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.add(p);
//f.pack();
f.setSize(200, 200);
f.setLocation(150, 150);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
AutoWrapInJTable autoWrapInJTable = new AutoWrapInJTable();
}
});
}
}
class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
private final Color evenColor = new Color(230, 240, 255);
public TextAreaCellRenderer() {
super();
setLineWrap(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
setBackground((row % 2 == 0) ? evenColor : getBackground());
}
setFont(table.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}