Java JTable setValueAt StackOverflower错误
我搜索了一整天,仍然找不到解决问题的简单方法:当我在另一个单元格中编辑JTable cell时,如何让它更新其值? 我想以某种方式使用Java JTable setValueAt StackOverflower错误,java,swing,jtable,stack-overflow,Java,Swing,Jtable,Stack Overflow,我搜索了一整天,仍然找不到解决问题的简单方法:当我在另一个单元格中编辑JTable cell时,如何让它更新其值? 我想以某种方式使用fireTableCellUpdated,但我真的不明白如何使用它,何时在什么对象上使用它 我想得到的是某种类型的监听器,无论值是否改变,它都会监听。在这个特定的场景中,我有一个可编辑的第三列,我在其中存储了金额,我希望侦听器自动计算并设置行中其他单元格中的值。我想出了这样的办法: @Override public void tableChanged(TableM
fireTableCellUpdated
,但我真的不明白如何使用它,何时在什么对象上使用它
我想得到的是某种类型的监听器,无论值是否改变,它都会监听。在这个特定的场景中,我有一个可编辑的第三列,我在其中存储了金额,我希望侦听器自动计算并设置行中其他单元格中的值。我想出了这样的办法:
@Override
public void tableChanged(TableModelEvent e)
{
BigDecimal withoutTax, tax, withTax;
for(int i = 0; i < table.getRowCount(); i++)
{
BigDecimal amount = new BigDecimal(String.valueOf(table.getValueAt(i, 3)).replace(",", "."));
BigDecimal price = new BigDecimal(String.valueOf(table.getValueAt(i, 4)).replace(",", "."));
withoutTax = amount.multiply(price, new MathContext(2));
table.setValueAt(withoutTax, i, 5);
tax = withoutTax.multiply(new BigDecimal(0.23), new MathContext(2));
table.setValueAt(tax, i, 7);
withTax = withoutTax.add(tax, new MathContext(2));
table.setValueAt(withTax, i, 8);
}
}
@覆盖
公共作废表已更改(TableModelEvent e)
{
大十进制无税,税,有税;
对于(int i=0;i
但这会导致StackOverflowerError
,我猜这是因为table.setValueAt
触发tableChanged
侦听器,所以它将进入无限循环
有人能告诉我如何实现吗?
tableChanged
在发生对TableModel
的更改时被调用,该更改由setValueAt
方法触发,然后在您周围
解决方案是什么?在TableModel
的setValue
方法中执行此操作
public class TestModel extends ... { // Some TableModel
//...
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 3) {
// Set the value been passed to in (probably from the editor)...
fireTableCellUpdated(rowIndex, columnIndex);
BigDecimal amount = new BigDecimal(String.valueOf(getValueAt(rowIndex, 3)).replace(",", "."));
BigDecimal price = new BigDecimal(String.valueOf(getValueAt(rowIndex, 4)).replace(",", "."));
BigDecimal withoutTax = amount.multiply(price, new MathContext(2));
// Set the value for row x 5 directly within the backing store of the model...
//table.setValueAt(withoutTax, i, 5);
BigDecimal tax = withoutTax.multiply(new BigDecimal(0.23), new MathContext(2));
// Set the value for row x 7 directly within the backing store of the model...
//table.setValueAt(tax, i, 7);
BigDecimal withTax = withoutTax.add(tax, new MathContext(2));
// Set the value for row x 8 directly within the backing store of the model...
//table.setValueAt(withTax, i, 8);
fireTableCellUpdated(rowIndex, 5);
fireTableCellUpdated(rowIndex, 7);
fireTableCellUpdated(rowIndex, 8);
// It might actually be easier to use...
//fireTableRowsUpdated(rowIndex, rowIndex);
}
}
例如
public class MultiplicationTableMode extends AbstractTableModel {
private List<Integer> values;
public MultiplicationTableMode() {
values = new ArrayList<>(1);
values.add(0);
}
@Override
public int getRowCount() {
return values.size();
}
@Override
public int getColumnCount() {
return 10;
}
@Override
public String getColumnName(int column) {
return column == 0 ? "?" : "x" + Integer.toString(column);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
int value = values.get(rowIndex);
if (columnIndex > 0) {
value *= columnIndex;
}
return value;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
if (aValue instanceof Integer) {
values.set(rowIndex, (int)aValue);
fireTableRowsUpdated(rowIndex, rowIndex);
}
}
}
}
这是一个基本的例子,虽然它只使用一行,但这一想法同样适用于多行
tableChanged
在对TableModel
进行更改时被调用,该更改由setValueAt
方法触发,并在您周围
解决方案是什么?在TableModel
的setValue
方法中执行此操作
public class TestModel extends ... { // Some TableModel
//...
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 3) {
// Set the value been passed to in (probably from the editor)...
fireTableCellUpdated(rowIndex, columnIndex);
BigDecimal amount = new BigDecimal(String.valueOf(getValueAt(rowIndex, 3)).replace(",", "."));
BigDecimal price = new BigDecimal(String.valueOf(getValueAt(rowIndex, 4)).replace(",", "."));
BigDecimal withoutTax = amount.multiply(price, new MathContext(2));
// Set the value for row x 5 directly within the backing store of the model...
//table.setValueAt(withoutTax, i, 5);
BigDecimal tax = withoutTax.multiply(new BigDecimal(0.23), new MathContext(2));
// Set the value for row x 7 directly within the backing store of the model...
//table.setValueAt(tax, i, 7);
BigDecimal withTax = withoutTax.add(tax, new MathContext(2));
// Set the value for row x 8 directly within the backing store of the model...
//table.setValueAt(withTax, i, 8);
fireTableCellUpdated(rowIndex, 5);
fireTableCellUpdated(rowIndex, 7);
fireTableCellUpdated(rowIndex, 8);
// It might actually be easier to use...
//fireTableRowsUpdated(rowIndex, rowIndex);
}
}
例如
public class MultiplicationTableMode extends AbstractTableModel {
private List<Integer> values;
public MultiplicationTableMode() {
values = new ArrayList<>(1);
values.add(0);
}
@Override
public int getRowCount() {
return values.size();
}
@Override
public int getColumnCount() {
return 10;
}
@Override
public String getColumnName(int column) {
return column == 0 ? "?" : "x" + Integer.toString(column);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
int value = values.get(rowIndex);
if (columnIndex > 0) {
value *= columnIndex;
}
return value;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
if (aValue instanceof Integer) {
values.set(rowIndex, (int)aValue);
fireTableRowsUpdated(rowIndex, rowIndex);
}
}
}
}
这是一个基本的例子,虽然它只使用一行,但这一想法同样适用于多行
tableChanged
在对TableModel
进行更改时被调用,该更改由setValueAt
方法触发,然后在您周围执行…解决方案?在setValue
方法中执行该操作,并触发范围updateHmm,您的意思是像在表模型中重写setValue()一样?你说的“范围更新”是什么意思。我的意思是“范围更新”是使用fireTableRowsUpdated
一步更新整行可能更有效,而不是在对TableModel
进行更改时尝试在4个单独的事件调用中更新4个单元格,由setValueAt
方法触发,然后在您周围…解决方案?在setValue
方法中执行该操作,并触发范围updateHmm,您的意思是像在表模型中重写setValue()一样?你说的“范围更新”是什么意思。我的意思是“范围更新”是使用fireTableRowsUpdated
一步更新整行可能更有效,而不是尝试在4个单独的事件调用中更新4个单元格,这就解释了很多问题,我将在几分钟内尝试它这是“一般”想法;)嘿,等一下。当我触发该方法时,仍然不能解决问题?我的意思是,我需要某种while(true)
循环来检查值是否发生了变化,如果发生了变化,则会触发setValueAt
,我不确定我是否理解。当单元格编辑器“停止”时,JTable
将调用TableModel
的setValueAt
方法,这将允许您确定已更新的值(单元格的新值),然后进行二次计算,为什么需要调用setValueAt
?是和否。DefaultTableModel
可以,但是AbstractTableModel
不可以,这就是(正如您在两个示例中看到的)我亲自调用fireXxx
方法的原因。现在,这解释了很多问题,我将在几分钟内尝试一下这是“一般”想法;)嘿,等一下。当我触发该方法时,仍然不能解决问题?我的意思是,我需要某种while(true)
循环来检查值是否发生了变化,如果发生了变化,则会触发setValueAt
,我不确定我是否理解。当单元格编辑器“停止”时,JTable
将调用TableModel
的setValueAt
方法,这将允许您确定已更新的值(单元格的新值),然后进行二次计算,为什么需要调用setValueAt
?是和否。DefaultTableModel
有,但AbstractTableModel
没有,这就是我自己实际调用fireXxx
方法的原因(如两个示例所示)