简体   繁体   English

如何实时更新 Swing GUI - JAVA

[英]How to update Swing GUI in realtime - JAVA

I am writing a java program to get realtime stock data.我正在编写一个 java 程序来获取实时库存数据。 I used the URL class to get the information from yahoo finance.我使用URL class从雅虎财经获取信息。 I am able to get all the information I need using a class for the stock.我可以使用 class 获取所需的所有信息。 However, I want the GUI to update the value of the stock price every second or half second by calling a method that get the price of the stock, and update the value in a JLabel every second.但是,我希望 GUI 通过调用获取股票价格的方法每秒或半秒更新一次股票价格的值,并每秒更新 JLabel 中的值。 So essentially, how do I update a value in Swing GUI by calling a method every second?所以本质上,我如何通过每秒调用一个方法来更新 Swing GUI 中的值? Thank you.谢谢你。

There are a number of ways you might achieve this.您可以通过多种方式实现这一目标。 A Swing Timer is a good choice to generate calls backs (into the Event Dispatching Thread) after a specified delay. Swing Timer是在指定延迟后生成回调(进入事件调度线程)的不错选择。

But what you probably want to is schedule a callback to perform the request and once it's completed, update the UI and schedule another callback.但是您可能想要安排一个回调来执行请求,一旦完成,更新 UI 并安排另一个回调。 The point been, the actual request might take longer to call/process than the amount of time you've allocated between calls.关键是,实际请求的调用/处理时间可能比您在调用之间分配的时间长。

The following makes use of SwingWorker to perform the actual "work", using a random delay of between 1-5 seconds, once completed, it notifies a "observer" of some new state (in this case, just some nice messages).下面使用SwingWorker执行实际的“工作”,使用 1-5 秒之间的随机延迟,一旦完成,它会通知“观察者”一些新的 state(在这种情况下,只是一些不错的消息)。

Once the worker completes, a new worker is scheduled, using a ScheduledExecutorService (although you could do it manually with a Swing Timer )一旦工作人员完成,就会使用ScheduledExecutorService安排一个新工作人员(尽管您可以使用 Swing Timer手动完成)

See Concurrency in Swing请参阅Swing 中的并发

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;

public class Test {
    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);

        private JLabel label;

        public TestPane() {
            setBorder(new EmptyBorder(16, 16, 16, 16));            
            label = new JLabel("Nothing happening here, just waiting for stuff");
            setLayout(new GridBagLayout());
            add(label);

            startNextWorker();
        }

        protected void startNextWorker() {
            ExecutorWorker worker = new ExecutorWorker(new ExecutorWorker.Observer() {
                @Override
                public void workerDidUpdate(String message) {
                    label.setText(message);
                }
            });
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (worker.getState() == SwingWorker.StateValue.DONE) {
                        worker.removePropertyChangeListener(this);
                        startNextWorker();
                    }
                }
            });
            service.schedule(worker, 1500, TimeUnit.MILLISECONDS);
        }

    }

    public class ExecutorWorker extends SwingWorker<Void, String> {

        public interface Observer {
            public void workerDidUpdate(String message);
        }

        private Random rnd = new Random();
        private Observer observer;

        public ExecutorWorker(Observer observer) {
            this.observer = observer;
        }

        @Override
        protected Void doInBackground() throws Exception {
            publish("Starting some new work, back in a seocnd");
            Thread.sleep(1000 + rnd.nextInt(5000));
            publish("All the work is now done");
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String messages : chunks) {
                observer.workerDidUpdate(messages);
            }
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM