为什么在接收更改事件时不要更改通知程序 [英] Why never change the notifier in receiving a change event

查看:97
本文介绍了为什么在接收更改事件时不要更改通知程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发布了 Java TableModelListener和Live Feed Listener? / a>,但是我得到一个评论 - kleopatra

I posted an answer to Java TableModelListener and Live Feed Listener?, but I get a comment by – 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.

可以让我解释一下,在接收到更改事件时,通知者有什么改变,可能会发生什么她真的意味着,因为当我尝试我所知道的一切,我只是从很快的循环中收到RepaintManager异常,

can somone to explain me what's Change the notifier in receiving a Change Event, what could be happen, what she really means, because as I tried everything that I know that I only receiving RepaintManager Exceptions from very quickly loop,

我从来没有得到另一个例外,其中

I never get another Exception, where


  • 我将这个与50x 1000矩阵相乘,

  • I multiplaeyd that to the 50 x 1000 matrix,

与prepareRenderer (更改可能/负值的颜色)

with prepareRenderer (change Color for possitive/negative value)

刷新率为175毫秒

代码演示了更改通知器和另外两个(可能是正确的)方式,如何做到这一点

code demonstrated changing the notifier and two another (maybe correct) way how do that

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


推荐答案

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

I think she means that if you don't really think about your code then you can introduce an infinite loop.

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

Most people when when they create the table would probably make columns 1, 2 editable and make column 3 uneditable since column 3 is just the difference between the two columns.

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

So when they write the TableModelListener they will check for the UPDATE event but forget to check to see which column is updated because they think the table won't allow them to update column 3.

他们忘记当TableModelListener更新列3另一个UPDATE事件将会产生无限循环。当然,正确的编码就像在你的例子中一样会阻止循环。

They forget that when the TableModelListener updates column 3 another UPDATE event will be generated thus causing the infinite loop. Of course, proper coding, like in your example, will prevent the loop.

一般来说,它不应该引起异常。

In general, it should not cause an exception.

第二点是业务规则。业务规则应该在一个地方定义,在这种情况下应该是模型。数据本身和数据的更新应该在一个地方完成。

The second point is about business rules. The business rules should be defined on one place, in this case the model. The data itself and the updating of the data should be done in a single place.

这篇关于为什么在接收更改事件时不要更改通知程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆