在我的应用程序中,我使用了一个类似于this示例的java表。我的问题是,当我更改单元格的值时(即使在上面的示例中),在我单击其他单元格之前,数据模型不会更新。即使我在更改单元格值后单击表格下方的灰色区域,模型也不会更改。我认为原因是细胞保持专注,直到我点击不同的细胞。如何避免这种情况并更新模型而不单击表格单元格。提前致谢
我已编辑上面的示例代码以反映问题
public class JTableDemo extends JApplet {
private JTextArea txt = new JTextArea(4, 20);
// The TableModel controls all the data:
class DataModel extends AbstractTableModel {
Object[][] data = { { "one", "two", "three", "four" },
{ "five", "six", "seven", "eight" },
{ "nine", "ten", "eleven", "twelve" }, };
// Prints data when table changes:
class TML implements TableModelListener {
public void tableChanged(TableModelEvent e) {
txt.setText(""); // Clear it
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++)
txt.append(data[i][j] + " ");
txt.append("\n");
}
}
}
public DataModel() {
addTableModelListener(new TML());
fireTableDataChanged();
}
public int getColumnCount() {
return data[0].length;
}
public int getRowCount() {
return data.length;
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public void setValueAt(Object val, int row, int col) {
data[row][col] = val;
System.out.println(val);
// Indicate the change has happened:
fireTableDataChanged();
}
public boolean isCellEditable(int row, int col) {
return true;
}
}
public void init() {
Container cp = getContentPane();
JTable table = new JTable(new DataModel());
cp.add(new JScrollPane(table));
cp.add(BorderLayout.SOUTH, txt);
}
public static void main(String[] args) {
run(new JTableDemo(), 350, 200);
}
public static void run(JApplet applet, int width, int height) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(applet);
frame.setSize(width, height);
applet.init();
applet.start();
frame.setVisible(true);
}
}
运行该示例时,您可以在表格下方的文本区域中看到表格内容。更新单元格后,它应显示在下面的文本框中。但是'setValueAt'方法在您单击其他单元格之前不会调用。
答案 0 :(得分:13)
这是预期的行为:在显式用户手势(如f.i)之前,编辑后的值不会提交给支持模型。按下输入或标签或点击表格中的其他地方...
JTable的一个奇怪之处(有人称之为bug :-)是在将焦点转移到表格的“外部”时默认不会终止编辑。要强制它这样做,您需要将其配置为:
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
BTW(无关,只是为了理智):总是激活最细粒度的事件类型,这里将是一个cellUpdated而不是dataChanged锤。
答案 1 :(得分:8)
默认更新机制仅在单元格编辑器失去焦点时更改模型。从单元格中跳出或单击不同的单元格将导致重要的“焦点丢失”事件,从而触发模型更改。
单击灰色区域无效,因为那里没有可以处理事件的活动元素 - 表格忽略了点击。
如果要更改此设置,则需要找到一个事件,告诉计算机用户“已完成编辑”。你怎么知道?
ActionListener
(请参阅http://download.oracle.com/javase/tutorial/uiswing/components/textfield.html)。按RETURN时会触发它。在处理程序中,调用fireEditingStopped()
以触发“复制到模型”代码(请参阅http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editor)。您可以在表格下方添加“保存”按钮,并在其ActionListner
中调用此代码:
if(null != jTable.getCellEditor()) {
// there is an edit in progress
jTable.getCellEditor().stopCellEditing()
}
[编辑] 请注意,添加“保存”按钮可以中断用户的编辑“流程”(单击表格单元格,编辑,抓取鼠标,瞄准,单击保存,单击下一个单元格,然后转到回到键盘,编辑,...)
答案 2 :(得分:0)
对于我来说
public void setValueAt(Object val, int row, int col) {
data[row][col] = val;
System.out.println(val);
// Indicate the change has happened:
fireTableDataChanged();
}
您还需要调用超级函数。
public void setValueAt(Object val, int row, int col) {
data[row][col] = val;
System.out.println(val);
// Indicate the change has happened:
fireTableDataChanged();
super.setValueAt(val,row,col);
}