为什么不改变通知者接收更改事件

我发布了Java TableModelListener和Live Feed Listener的答案? ,但是我得到了 – kleopatra的评论

nonono - you never change the notifier in receiving a change event. As to probable effects, think: nasty loops. As to code sanity, think: indecent intimacy. It's the task of the model itself to internally update related values if necessary. 

可以somone来解释我什么是在接收Change Event中更改通知程序,可能发生的事情,她的真正含义,因为当我尝试了所有我知道我只从非常快的循环中接收RepaintManager Exceptions时,

我从来没有得到另一个exception,在哪里

  • 我multiplaeyd,到50×1000matrix,

  • 与prepareRenderer(更改颜色的正负值)

  • 刷新率为175毫秒

代码演示了如何更改通知程序和另外两个(也许是正确的)方式

 import java.awt.*; import java.awt.event.ActionEvent; import java.util.Random; import java.util.concurrent.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.DefaultTableModel; public class ChangeNotifiersOnEvent extends JFrame implements Runnable { private static final long serialVersionUID = 1L; private boolean runProcess = true; private Random random = new Random(); private javax.swing.Timer timerRun; private Executor executor = Executors.newCachedThreadPool(); private String[] columnNames = {"Source", "Hit", "Last", "Ur_Diff"}; private JTable table; private Object[][] data = {{"Swing Timer", 2.99, 5, 1.01}, {"Swing Worker", 7.10, 5, 1.010}, {"TableModelListener", 25.05, 5, 1.01}}; private DefaultTableModel model = new DefaultTableModel(data, columnNames); public ChangeNotifiersOnEvent() { table = new JTable(model) { private static final long serialVersionUID = 1L; @Override public Class getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; model.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent tme) { if (tme.getType() == TableModelEvent.UPDATE) { if (tme.getColumn() == 1 && tme.getLastRow() == 2) { double dbl = ((Double) table.getModel().getValueAt(2, 1)) - ((Integer) table.getModel().getValueAt(2, 2)); table.getModel().setValueAt(dbl, 2, 3); } else if (tme.getColumn() == 1 && tme.getLastRow() == 0) { prepareUpdateTableCell(); } else if (tme.getColumn() == 1 && tme.getLastRow() == 1) { executor.execute(new MyTask(MyTask.UPDATE_TABLE_COLUMN)); } } } }); table.setRowHeight(30); table.setFont(new Font("Serif", Font.BOLD, 20)); table.getColumnModel().getColumn(0).setPreferredWidth(180); table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane scrollPane = new JScrollPane(table); add(scrollPane, BorderLayout.CENTER); new Thread(this).start(); } private void prepareUpdateTableCell() { timerRun = new javax.swing.Timer(10, UpdateTableCell()); timerRun.setRepeats(false); timerRun.start(); } private Action UpdateTableCell() { return new AbstractAction("Update Table Cell") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { double dbl = ((Double) table.getModel().getValueAt(0, 1)) - ((Integer) table.getModel().getValueAt(0, 2)); table.getModel().setValueAt(dbl, 0, 3); } }; } @Override public void run() { while (runProcess) { try { Thread.sleep(250); } catch (Exception e) { e.printStackTrace(); } changeTableValues(); } } private void changeTableValues() { Runnable doRun = new Runnable() { @Override public void run() { table.getModel().setValueAt(random.nextInt(128) + random.nextDouble(), 0, 1); table.getModel().setValueAt(random.nextInt(256) + random.nextDouble(), 1, 1); table.getModel().setValueAt(random.nextInt(512) + random.nextDouble(), 2, 1); table.getModel().setValueAt(random.nextInt(128), 0, 2); table.getModel().setValueAt(random.nextInt(128), 1, 2); table.getModel().setValueAt(random.nextInt(128), 2, 2); } }; SwingUtilities.invokeLater(doRun); } private class MyTask extends SwingWorker<Void, Integer> { private static final String UPDATE_TABLE_COLUMN = "update"; private String namePr; private double dbl; MyTask(String str) { this.namePr = str; } @Override protected Void doInBackground() throws Exception { dbl = ((Double) table.getModel().getValueAt(1, 1)) - ((Integer) table.getModel().getValueAt(1, 2)); return null; } @Override protected void done() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { table.getModel().setValueAt(dbl, 1, 3); } }); } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ChangeNotifiersOnEvent frame = new ChangeNotifiersOnEvent(); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setLocation(150, 150); frame.pack(); frame.setVisible(true); } }); } } 

我认为她的意思是如果你真的不考虑你的代码,那么你可以引入一个无限循环。

大多数人在创build表格时,可能会使第1,2列可编辑,并使第3列不可编辑,因为第3列仅仅是两列之间的差异。

所以当他们编写TableModelListener时,他们将检查UPDATE事件,但忘记检查哪个列被更新,因为他们认为该表不允许他们更新第3列。

他们忘记了当TableModelListener更新第3列时,将会生成另一个UPDATE事件,从而导致无限循环。 当然,像你的例子一样,正确的编码将防止循环。

一般来说,它不应该引起例外。

第二点是关于业务规则。 业务规则应该在一个地方定义,在这个例子中是模型。 数据本身和数据的更新应该在一个地方完成。