gpt4 book ai didi

java - JTable setValueAt StackOverflowError

转载 作者:行者123 更新时间:2023-12-01 18:07:08 24 4
gpt4 key购买 nike

我已经搜索了一整天,但仍然找不到解决我的问题的简单答案:当我在另一个单元格中编辑它时,如何使 JTable 单元格更新它的值?

我想以某种方式使用 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);
}
}

但这会导致 StackOverflowError ,我猜测这是因为 table.setValueAt 触发了 tableChanged 监听器,因此它进入了无限循环。

有人可以解释一下我怎样才能做到这一点吗?

最佳答案

tableChangedTableModel 发生更改时被调用,这是由 setValueAt 方法触发的,并且在您周围...

解决方案?在 TableModelsetValue 方法中执行此操作...

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);
}
}

例如...

这是一个基本示例,虽然它只使用单行,但这个想法同样适用于多行......

Table

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

public TestPane() {
setLayout(new BorderLayout());
JTable table = new JTable(new MultiplicationTableMode());
add(new JScrollPane(table));
}

}

public class MultiplicationTableMode extends AbstractTableModel {

private List<List<Integer>> values;

public MultiplicationTableMode() {
values = new ArrayList<>(1);
List<Integer> cols = new ArrayList<>(11);
for (int index = 0; index < 11; index++) {
cols.add(0);
}
values.add(cols);
}

@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) {
List<Integer> columns = values.get(rowIndex);
return columns.get(columnIndex);
}

@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) {
List<Integer> columns = values.get(rowIndex);
int intValue = (int) aValue;
columns.set(0, intValue);
for (int index = 1; index < columns.size(); index++) {
columns.set(index, intValue * index);
}
fireTableRowsUpdated(rowIndex, rowIndex);
}
}
}

}

}

已更新...

我想到,如果其他列值不可编辑,那么您实际上根本不需要维护它们的值,而只需在调用 getValueAt 时动态计算它们,例如例子...

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);
}
}
}

}

关于java - JTable setValueAt StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35517299/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com