【问题标题】:How do you update a JLabel before a delay?您如何在延迟之前更新 JLabel?
【发布时间】:2019-11-28 09:56:02
【问题描述】:

当我尝试对我的代码使用任何类型的延迟时,程序会延迟,但在延迟之前放置的 JLabel 在程序结束后会更新。

我希望程序:

  • 在 GUI 上更新 JLabel
  • 等待 5 秒
  • 用不同的文本再次更新 JLabel
  • 再等 5 秒

我尝试过使用计时器、invokelater、invokeandwait、thread.sleep 等。

问题在于 GUI 确实在正确的位置延迟,但 GUI 没有更新代码所在位置的 JLabel。 JLabel 在程序结束后得到更新。

我希望用户能够按顺序阅读文本 5 秒,然后再阅读另一个文本 5 秒。我不希望程序在某个地方运行 gui 暂停,然后最后只更新 JLabel。我希望 gui 在延迟之前得到更新。我不希望发生同样的事情,当我使用计时器时,我在键入计时器之前为 JLabel 输入 setText,然后当我运行程序时,计时器工作但 JLabel 在延迟后得到更新(它是不是我想要的)。

【问题讨论】:

  • 显示您尝试过的内容。我怀疑事件调度线程的使用不当
  • 请在此处添加一些代码以详细了解问题

标签: java


【解决方案1】:

实现这一点的方法是using a Swing Worker,或者a Swing Timer。 Swing 工作人员在后台运行任务,同时它能够在 事件调度线程(运行 GUI 的线程)中发布 GUI 更改。 SwingTimer 可以被认为是 Swing Worker 的简化版本,它只在 Event Dispatch Thread 中运行一段时间后的任务。 (假设有一个worker在后台sleeps线程,在sleep之后,它在Gui线程中运行任务。

网上有很多例子,比如this onethis one

如果您不想在后台做某事,Timer 解决方案听起来“更简单”。看看How can I pause/sleep/wait in a java swing app?

一个更接近您需要的示例(使用工人):

public class WorkerExample extends JFrame {
    private static final long serialVersionUID = 6230291564719983347L;
    private JLabel label;

    public WorkerExample() {
        super("");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setLayout(new FlowLayout());

        SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {

            @Override
            protected Void doInBackground() throws Exception {
                publish("Started....");
                Thread.sleep(1500);
                for (int i = 0; i < 5; i++) {
                    publish("Number of iterations: " + i);
                    //Do something
                    Thread.sleep(3500);
                }
                return null;
            }

            @Override
            protected void process(List<String> chunks) {
                String chunk = chunks.get(0);
                label.setText(chunk);
            }

            @Override
            protected void done() {
                label.setText("Done.");
            }
        };

        JButton button = new JButton("Start");
        button.addActionListener(e -> worker.execute());
        add(button);

        label = new JLabel("Nothing yet.");
        add(label);

        setSize(400, 400);
        setLocationByPlatform(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new WorkerExample().setVisible(true);
        });
    }
}

您可以尝试这些以了解SwingWorker 的工作原理,但我强烈建议您在这样做之前阅读concurrency in Swing

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 2019-07-10
    • 2015-04-04
    • 1970-01-01
    • 2021-01-31
    • 2023-02-09
    相关资源
    最近更新 更多