【问题标题】:Component waits for later code to execute before it draws组件在绘制之前等待后面的代码执行
【发布时间】:2015-12-29 00:44:59
【问题描述】:

我有一个名为 WaitBox 的类,我想弹出它,显示一个进度条,然后在进度条达到 100% 时关闭。现在,它弹出来了,但奇怪的是它等到代码完成后才在WaitBox中绘制组件(进度条)...

当我运行下面的代码时,JDialog 会弹出,但它只是白色的,就像在其上绘制组件之前的样子。它运行它下面的代码(嵌套的 for 循环),完成后,它在 JDialog 上绘制组件。为什么会发生这种情况,我该如何解决?

WaitBox 类:

public class WaitBox extends JDialog implements Runnable {
private static final long serialVersionUID = 1L;

private int width = 450;
private int height = 200;
public static int widthOfBar = 400;
private int heightOfBar = 50;
private JPanel container;
private JProgressBar progressBar;
private Thread thread;
private boolean running = false;

public WaitBox() {
    initializeComponents();
    add(container);
    pack();
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    setTitle("Loading...");
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setResizable(false);
    setLocationRelativeTo(null);
    setVisible(true);
}

private void initializeComponents() {
    container = new JPanel();
    container.setPreferredSize(new Dimension(width, height));
    progressBar = new JProgressBar(0, widthOfBar);
    progressBar.setPreferredSize(new Dimension(widthOfBar, heightOfBar));
    progressBar.setStringPainted(true);
    progressBar.setValue(0);
    container.add(progressBar);
}

public void run() {
    while (running) {
        System.out.println(Fill.currentPos);
        progressBar.setValue((int) Fill.currentPos);
        if (progressBar.getValue() >= widthOfBar) running = false;
    }
    stop();
}

public synchronized void start() {
    running = true;
    thread = new Thread(this);
    thread.start();
}

public synchronized void stop() {
    running = false;
    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    setCursor(null);
    dispose();
}

}

如何称呼:

WaitBox waitBox = new WaitBox();
waitBox.start();
for (int yy = 0; yy < Constants.map_height; yy++) {
    for (int xx = 0; xx < Constants.map_width; xx++) {
        image.setRGB(xx * 32, yy * 32, 32, 32, pixels, 0, 32);
    }
}

【问题讨论】:

    标签: java swing jdialog jprogressbar


    【解决方案1】:

    您的stop 方法正在等待thread 结束,这会阻塞事件调度线程。

    详情请见Concurrency in Swing

    您的run 方法违反了 Swing 的单线程规则,从事件调度线程外部更新 UI,请记住,Swing 是单线程的,但也不是线程安全的。

    您应该考虑改用SwingWorker,它有进步和PropertyChange 支持。详情请见Worker Threads and SwingWorker

    演示:

    在其他地方

    【讨论】:

    • 我可以在我的构造函数中启动一个 SwingWorker,或者您建议将它放在哪里?
    • 您可以随时随地启动它。它使用自己的后台线程来调用doInBackground 方法。您应该使用PropertyChangeListener 支持和/或publish/process 功能来更新用户界面
    • 我添加了一个 SwingWorker 并将所有运行/WaitBox 的东西放在里面,它就像我想要的那样工作。非常感谢!
    猜你喜欢
    • 2015-06-03
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多