0

我正在用 JFreeChart 编写温度计,但我不想看到它只显示一个值...我需要将最终值放入 JTextField(然后按下按钮)并查看水银如何从 0º 变为比最终值,我想看看水银是如何上升的。

我用 Thread.sleep(500) 做了一个 FOR(从 0 到最终值),然后用 FOR 中的索引更新数据集值,但它没有显示转换,它完成了 FOR最后返回显示最终值的温度计。我试图刷新图表,但没有奏效。

我的按钮中的代码

final JButton btnAccept = new JButton("Accept");
    btnAceptar.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            for(int i = 0; i <= 40; i++) {
                    try {
                        Thread.sleep(500);
                    } 
                    catch(InterruptedException ex) {
                        Thread.currentThread().interrupt();
                    }
                    dataset.setValue(i);
                }
        }
    });
    panel.add(btnAceptar);
4

1 回答 1

1

Swing 是一个单线程框架。也就是说,对 UI 的所有交互和修改都应该在事件调度线程的内容中执行。

任何阻塞此线程的操作都会阻止 EDT 开始处理重绘请求和处理新事件(以及其他事情)。

您在这里遇到的问题是actionPerformed事件是从 EDT 的上下文中触发的。您的for-next循环现在阻塞了 EDT,阻止处理任何绘画请求......

你可以...

使用 ajavax.swing.Timer定期触发事件并更新dataset值,直到它达到您想要的目标,然后停止计时器。

例如...

final JButton btnAccept = new JButton("Accept");
btnAceptar.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        dataset.setValue(0);
        Timer timer = new Timer(500, new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                int current = dataset.getValue();
                if (current < 40) {
                    current++;
                    dataset.setValue(current);
                } else {
                    ((Timer)evt.getSource()).stop();
                }
            }
        });
        timer.start();
    }
});
panel.add(btnAceptar);

你可以...

使用在其方法SwingWorker中使用for-next循环的a doInBackground,发布新值,该值将对其process方法可用,该方法在 EDT 的上下文中执行...

例如...

final JButton btnAccept = new JButton("Accept");
btnAceptar.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        SwingWorker worker = new SwingWorker<Object, Integer> {
            protected Object doInBackground() {
                for(int i = 0; i <= 40; i++) {
                    try {
                        Thread.sleep(500);
                    } 
                    catch(InterruptedException ex) {
                        break;
                    }
                    publish(i);
                }
            }                

            protected void process(List<Integer> chunks) {
                // Only care about the last update...
                dataset.setValue(chunks.get(chunks.size() - 1));
            }
        }
    }
});
panel.add(btnAceptar);

你可以...

滚动你自己的Thread,这将for-next在方法中使用一个循环run,但你必须在 EDT 的上下文中使用它SwingUtilities.invokeLater来更新dataset,这既麻烦又麻烦,尤其是在使用其他两个选项时......

查看Swing 中的并发以获取更多详细信息

于 2013-08-15T00:14:37.343 回答