我有一个可编辑的JTable。当用户输入时,如果文本比宽度长,我需要增加高度。我已将linewrap设置为true,但它仅在用户按Enter后更改高度。我错过了什么?我已经查看了解决调整大小问题的答案(例如cellRenderer中的this,但我需要在用户输入时调整高度,而不是在完成输入后调整高度。
public class EndCycleCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener {
JComponent component;
private ArrayList<ArrayList<Integer>> rowColHeight = new ArrayList<ArrayList<Integer>>();
public EndCycleCellEditor(){
component = new JTextArea();
((JTextArea) component).setWrapStyleWord(true);
((JTextArea) component).setLineWrap(true);
component.addKeyListener(this);
}
@Override
public Object getCellEditorValue() {
return ((JTextArea) component).getText();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
((JTextArea)component).setText(value.toString());
return component;
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
if(((JTextArea) component).getText().length() >= 200){
Toolkit.getDefaultToolkit().beep();
((JTextArea)component).setText(((JTextArea)component).getText().substring(0,200) );
}
}
}
答案 0 :(得分:4)
1)这种方式调整大小是可能的,但丑陋而不是user_friendly
2)不要使用非标准黑客作为JTable中的MultiLines跨度
3)将JTextArea添加到JScrollPane,但是您必须覆盖另一个JScrollPane
内的滚动JScrollPane
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
class JTableMultiLineSupport extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = 1L;
private JTextArea editor = new JTextArea(4, 10);
private JScrollPane jsp = new JScrollPane(editor);
private JTable table;
private int row;
private int col;
private JTextArea renderer = new JTextArea(4, 10);
public static void main(String[] args) {
JTable table = new JTable(new String[][]{
{"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"},
{"1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7", "1\n2\n3\n4\n5\n6\n7"}},
new String[]{"First Column", "Second Column", "Third Column"});
JTableMultiLineSupport mls = new JTableMultiLineSupport();
table.setDefaultEditor(Object.class, mls);
table.setDefaultRenderer(Object.class, mls);
table.setRowHeight(0, 30);
table.setRowHeight(1, 70);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JFrame frame = new JFrame("Test");
frame.add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int col) {
this.table = table;
this.row = row;
this.col = col;
editor.setText(value.toString());
return jsp;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
renderer.setText(value == null ? "" : value.toString());
renderer.setEnabled(false);
return renderer;
}
@Override
public Object getCellEditorValue() {
return editor.getText();
}
@Override
public boolean stopCellEditing() {
table.getModel().setValueAt(editor.getText(), row, col);
return true;
}
}
答案 1 :(得分:0)
[编辑:我的初步答案有一些错误和影响。同时,我根据各种例子找到了一个更优雅的解决方案。]
此解决方案基于http://www.coderanch.com/t/336033/GUI/java/MultiLine-JTable - 但我做了一些错误修正(主要是:从编辑器中删除了rowHeights的计算,将rowHeight的计算添加到渲染器中)。
http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx上的建议非常有用,可以让它更漂亮(例如为表格添加颜色和字体)。
总之,这个解决方案使JTable单元具有多条线。输入或删除文本时,编辑器会自动更新行高。行高的计算留给TextArea的preferredSize。
第一步:CellRenderer
public class MultiLineCellRenderer extends JTextArea implements
TableCellRenderer {
public MultiLineCellRenderer() {
setEditable(false);
setLineWrap(true);
setWrapStyleWord(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof String) {
setText((String) value);
// We set the width and force textarea to recompute the preferred height
setSize(table.getColumnModel().getColumn(column).getWidth(), 1000);
// we should not do the following in this method.
// it seems to create an endless loop
// int rowHeight = table.getRowHeight(row);
// int cellHeight = getPreferredSize().height;
// if (cellHeight > rowHeight)
// table.setRowHeight(row, cellHeight);
} else
setText("");
return this;
}
/*
* Make sure to call this method, whenever the table changes.
* Call it from appropriate TableCellRenderer, TableModelListener,
* ComponentListener, TableColumnModelListener.
*/
public void updateRowHeights() {
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = 0;
for (int col = 0; col < table.getColumnCount(); col++) {
Object value = table.getValueAt(row, col);
if (value != null)
setText(value.toString());
else
setText("");
setSize(table.getColumnModel().getColumn(col).getWidth(), 1000);
int cellHeight = getPreferredSize().height;
if (cellHeight > rowHeight)
rowHeight = cellHeight;
}
table.setRowHeight(row, rowHeight);
}
}
}
第2步:CellEditor(我假设可以使用更短的解决方案,而不会覆盖JTextArea)。
public class MultiLineCellEditor extends AbstractCellEditor implements
TableCellEditor {
MyTextArea textArea;
JTable table;
public MultiLineCellEditor(JTable ta) {
super();
table = ta;
// this component relies on having this renderer for the String
// class
MultiLineCellRenderer renderer = new MultiLineCellRenderer();
table.setDefaultRenderer(String.class, renderer);
textArea = new MyTextArea();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
}
public Object getCellEditorValue() {
return textArea.getText();
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
textArea.setText(table.getValueAt(row, column).toString());
textArea.rowEditing = row;
textArea.columnEditing = column;
textArea.lastPreferredHeight = textArea.getPreferredSize().height;
return textArea;
}
/**
* This method determines the height in pixel of a cell given the text it
* contains
*/
private int cellHeight(int row, int col) {
if (row == table.getEditingRow() && col == table.getEditingColumn())
return textArea.getPreferredSize().height;
else
return table
.getDefaultRenderer(String.class)
.getTableCellRendererComponent(table,
table.getModel().getValueAt(row, col), false,
false, row, col).getPreferredSize().height;
}
void cellGrewEvent(int row, int column) {
updateRow(row);
}
void cellShrankEvent(int row, int column) {
updateRow(row);
}
void updateRow(int row) {
int maxHeight = 0;
for (int j = 0; j < table.getColumnCount(); j++) {
int ch;
if ((ch = cellHeight(row, j)) > maxHeight) {
maxHeight = ch;
}
}
table.setRowHeight(row, maxHeight);
}
class MyTextArea extends JTextArea implements KeyListener {
private static final long serialVersionUID = 1L;
int lastPreferredHeight = 0;
int rowEditing;
int columnEditing;
MyTextArea() {
addKeyListener(this);
// This is a fix to Bug Id 4256006
addAncestorListener(new AncestorListener() {
public void ancestorAdded(AncestorEvent e) {
requestFocus();
}
public void ancestorMoved(AncestorEvent e) {
}
public void ancestorRemoved(AncestorEvent e) {
}
});
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
if (getPreferredSize().getHeight() > lastPreferredHeight) {
lastPreferredHeight = getPreferredSize().height;
cellGrewEvent(rowEditing, columnEditing);
// this will trigger the addition of extra lines upon the
// cell growing and prevent all the text being lost when
// the cell grows to the point of requiring scrollbars
table.setValueAt(getText(), rowEditing, columnEditing);
} else if (getPreferredSize().getHeight() < lastPreferredHeight) {
lastPreferredHeight = getPreferredSize().height;
cellShrankEvent(rowEditing, columnEditing);
} else if (table.getValueAt(rowEditing, columnEditing).equals(""))
table.setValueAt(getText(), rowEditing, columnEditing);
}
}
}
这里有一些测试代码。
public class MultiLineCellExample extends JFrame {
private static final long serialVersionUID = 1L;
public MultiLineCellExample() {
DefaultTableModel dm = new DefaultTableModel() {
private static final long serialVersionUID = 1L;
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
};
dm.setDataVector(
new Object[][] {
{ "aa TEST TEST TEST TEST TEST TEST TEST TEST END",
"bb", "cc" }, { "A\nA", "B\nB", "C\nC" } },
new Object[] { "1", "2", "3" });
JTable table = new JTable(dm);
MultiLineCellEditor editor = new MultiLineCellEditor(table);
table.setDefaultEditor(String.class, editor);
dm.fireTableRowsInserted(0, 0);
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
}
public static void main(String[] args) {
MultiLineCellExample mlce = new MultiLineCellExample();
mlce.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mlce.setSize(400, 400);
mlce.pack();
mlce.setVisible(true);
}
}