JTable 单元格更新不起作用
Posted
技术标签:
【中文标题】JTable 单元格更新不起作用【英文标题】:JTable Cell Update doesn't work 【发布时间】:2011-12-18 13:47:03 【问题描述】:在我的应用程序中,我使用了一个类似于 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”方法。
【问题讨论】:
你能编辑你的问题并添加一个SSCCE来显示问题吗? 【参考方案1】:这是预期的行为:编辑的值不会提交给支持模型,直到明确的用户手势,如 f.i.按回车键或跳出或单击表格中的其他位置...
JTable 的一个奇怪之处(有人称之为错误 :-) 是默认情况下,当将焦点转移到表格的“外部”时,编辑不会终止。要强制它这样做,您需要像这样配置它:
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
顺便说一句(无关,只是为了理智):总是触发最细粒度的事件类型,这里是 cellUpdated 而不是 dataChanged 锤子。
【讨论】:
我喜欢你的星期一,很棒且有价值的回答 +1【参考方案2】:默认更新机制仅在单元格编辑器失去焦点时更改模型。跳出单元格或单击不同的单元格都会导致触发模型更改的重要“焦点丢失”事件。
在灰色区域单击没有效果,因为那里没有可以处理事件的活动元素 - 表格忽略了单击。
如果你想改变它,你需要找到一个事件告诉计算机用户“完成编辑”。你怎么知道?
您可以添加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()
您可以通过添加按键处理程序来更新每个按键的模型,但这可能会导致编辑器消失。
[编辑]请注意,添加“保存”按钮可能会扰乱用户的编辑“流程”(单击表格单元格、编辑、抓住鼠标、瞄准、单击保存、单击下一个单元格、转到返回键盘,编辑,...)
【讨论】:
只需添加一个不执行任何操作且带有“保存”标签的按钮。连同 kleopatra 的答案中的客户端属性,这应该可以解决问题。请注意,这会极大地惹恼您的用户,因为这意味着额外的鼠标点击。尝试添加助记符,以便人们可以使用“Alt+S”停止编辑(无需离开键盘)。 no: a focusLost 默认情况下不会 触发提交(这是一个长期存在的问题,直到他们可以确信至少支持选择性地设置它行为)。实际上,tab 或单击另一个单元格的提交是由 tableUI 代码显式触发的 @Kleo:您可能错过了“连同来自 kleopatra 答案的客户端属性”。如果这不起作用,您需要在按钮的单击处理程序中调用单元格编辑器的fireEditingStopped()
。
我已经按照以下方式完成了。当用户单击保存 actionListner 中的保存按钮时,我调用 jTable.getCellEditor().stopCellEditing();方法。
注意 jTable.getCellEditor() 将返回 null 如果没有“正在进行”编辑【参考方案3】:
对于我来说
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);
【讨论】:
以上是关于JTable 单元格更新不起作用的主要内容,如果未能解决你的问题,请参考以下文章
滑动删除 UITableView 单元格动画在 swift 2 中不起作用
表格单元格中的 CSS 绝对定位在 Firefox 中不起作用