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

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

问题描述

我发布了一个对Java TableModelListener 和 Live Feed 监听器的回答?,但我收到了来自 – 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

  • 我将其乘以 50 x 1000 矩阵,

  • I multiplaeyd that to the 50 x 1000 matrix,

使用prepareRenderer(改变正/负值的颜色)

with prepareRenderer (change Color for possitive/negative value)

刷新率为 175 毫秒

with refresh rate 175 miliseconds

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

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天全站免登陆