Почему никогда не менять уведомителя при получении события изменения - PullRequest
5 голосов
/ 11 ноября 2011

Я отправил ответ на 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.

может кое-что объяснить мне, что изменит уведомитель при получении события изменения, что может произойти, что она на самом деле значит, потому что, поскольку я попробовал все, что я знаю, я получал только исключения 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 Ответ

6 голосов
/ 12 ноября 2011

Я думаю, она имеет в виду, что если вы на самом деле не думаете о своем коде, то можете ввести бесконечный цикл.

Большинство людей, когда при создании таблицы, вероятно, сделают столбцы 1, 2 редактируемыми истолбец 3 недоступен для редактирования, поскольку столбец 3 представляет собой разницу между двумя столбцами.

Поэтому, когда они пишут TableModelListener, они проверяют событие UPDATE, но забывают проверить, какой столбец обновлен, так как считают, что таблица выигралане позволяют им обновлять столбец 3.

Они забывают, что когда TableModelListener обновляет столбец 3, будет сгенерировано другое событие UPDATE, что вызовет бесконечный цикл.Конечно, правильное кодирование, как в вашем примере, предотвратит цикл.

В общем, оно не должно вызывать исключение.

Второй момент касается бизнес-правил.Бизнес-правила должны быть определены в одном месте, в данном случае это модель.Сами данные и обновление данных должны быть сделаны в одном месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...