当前位置: 首页 > 面试题库 >

为什么从不接收更改事件就永远不更改通知者

柯苗宣
2023-03-14
问题内容

我发布了Java TableModelListener和Live FeedListener的答案?,但我收到– 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异常的事情时,

我再也没有例外

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

  • 使用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);
            }
        });
    }
}

问题答案:

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

大多数人在创建表时可能会使第1列,第2列可编辑,使第3列不可编辑,因为第3列仅是两列之间的区别。

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

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

通常,它不应引起异常。

第二点是关于业务规则。业务规则应在一个地方定义,在这种情况下为模型。数据本身和数据更新应在一个地方进行。



 类似资料:
  • 我正试图阻止woo-commerce发送邮件时,订单状态更改。这些订单是亚马逊的,我的插件从亚马逊同步到Woo-Commerce。在这样做的时候,亚马逊和woo-commerce的邮件都收到了,这激怒了客户。因此,我想停止电子邮件功能停止时,状态从我的插件更改。要更改状态的代码是 有没有可以设置的标志来避免发送邮件? 任何种类的帮助都是非常感谢的。

  • 我正在使用,并在用户每次从drawer菜单中点击一个项目时添加一个新的。这很管用。 在其中一个中,用户可以导航到另一个片断: 这将正确地向堆栈中添加另一个。但是,它不会将操作栏抽屉按钮/图标更改为后退按钮。所以,在敲击那只是再次打开抽屉,这是不应该做的。返回的唯一方法是use The hardware back按钮,它返回到前面的。我尝试将以下内容添加到我的主中,以查看发生了什么: 但是只有当我使

  • 问题内容: 对于Oracle数据库表的任何更改(更新,插入,删除),我都需要一些侦听器。 问题:通过对表进行一次更新,我得到了很多检测。 我认为它的oracle缓存等 是否有可能仅检测到真正的变化? 我的代码: 输出: 问题答案: 问题是我多次注册到数据库。解决方案是在注册之前检查注册用户是否有更改事件。 我通过以下查询进行了检查:

  • 问题内容: 新手有问题,请保持温柔: 结果是: 我不明白为什么列表改变时,我只是在做,没有。我什至不知道要用什么搜索词来弄清楚。 问题答案: 这是因为在进行分配后,和都引用相同的列表。 尝试执行以下操作以查看它们是指相同的对象还是不同的对象: 一个例子: 如果您确实要创建这样的重复副本,而不是引用原始列表,而是引用列表的副本,请使用slice运算符: 一个例子: 另外,请勿将其用作变量名,因为最初

  • 为什么下面的印的是boss而不是BASS?

  • 然后它以对象数据类型的形式出现?我怎样才能让改变永久化?