java - 新线程 JDialog 中的 JProgressBar

标签 java multithreading swing concurrency jprogressbar

我想在新的 JDialog 中制作 JProgressBar,女巫将在与主逻辑不同的线程中。因此,我可以通过创建新的 JDialog 并通过处置 JDialog 来完成该进程来开始不确定的进程。但这让我很难实现这一目标,因为在 JDialog 出现后,它不会显示任何组件(包括 JProgressBar),直到主线程(SwingUtilities)中的逻辑完成。

包含 JDialog 的线程:

package gui.progress;

public class ProgressThread extends Thread {
    private ProgressBar progressBar = null;

    public ProgressThread() {
        super();
    }

    @Override
    public void run() {
        progressBar = new ProgressBar(null);
        progressBar.setVisible(true);
    }

    public void stopThread() {
        progressBar.dispose();
    }
}

JProgressBar 切换方法:

private static ProgressThread progressThread = null;
...
public static void toggleProcessBar() {
    if(progressThread == null) {
        progressThread = new ProgressThread();
        progressThread.start();
    } else {
        progressThread.stopThread();
        progressThread = null;
    }
}

最佳答案

But it gives me hard time to achieve that because after JDialog appears it doesn't show any components (including JProgressBar) until the logic in main thread (SwingUtilities) is done.

您对 Concurrency in Swing 有疑问, Swing 是单线程的,所有更新必须在 EventDispatchThread 上完成, 有两种方式

  • 易于使用 Runnable#Thread,但必须将输出到 Swing GUI 的内容包装到 invokeLater

  • 使用 SwingWorker ,有关 SwingWorker 的示例在 Oracles JProgressBar 中和 SwingWorker教程

编辑

此代码模拟违反 EDT 并为 SwingWorker 提供正确的解决方法

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

public class TestProgressBar {

    private static void createAndShowUI() {
        JFrame frame = new JFrame("TestProgressBar");
        frame.getContentPane().add(new TestPBGui().getMainPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowUI();
            }
        });
    }

    private TestProgressBar() {
    }
}

class TestPBGui {

    private JPanel mainPanel = new JPanel();

    public TestPBGui() {
        JButton yourAttempt = new JButton("Your attempt to show Progress Bar");
        JButton myAttempt = new JButton("My attempt to show Progress Bar");
        yourAttempt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                yourAttemptActionPerformed();
            }
        });
        myAttempt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                myAttemptActionPerformed();
            }
        });
        mainPanel.add(yourAttempt);
        mainPanel.add(myAttempt);
    }

    private void yourAttemptActionPerformed() {
        Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
        JDialog progressDialog = new JDialog(thisWin, "Uploading...");
        JPanel contentPane = new JPanel();
        contentPane.setPreferredSize(new Dimension(300, 100));
        JProgressBar bar = new JProgressBar(0, 100);
        bar.setIndeterminate(true);
        contentPane.add(bar);
        progressDialog.setContentPane(contentPane);
        progressDialog.pack();
        progressDialog.setLocationRelativeTo(null);
        Task task = new Task("Your attempt");
        task.execute();
        progressDialog.setVisible(true);
        while (!task.isDone()) {
        }
        progressDialog.dispose();
    }

    private void myAttemptActionPerformed() {
        Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
        final JDialog progressDialog = new JDialog(thisWin, "Uploading...");
        JPanel contentPane = new JPanel();
        contentPane.setPreferredSize(new Dimension(300, 100));
        final JProgressBar bar = new JProgressBar(0, 100);
        bar.setIndeterminate(true);
        contentPane.add(bar);
        progressDialog.setContentPane(contentPane);
        progressDialog.pack();
        progressDialog.setLocationRelativeTo(null);
        final Task task = new Task("My attempt");
        task.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equalsIgnoreCase("progress")) {
                    int progress = task.getProgress();
                    if (progress == 0) {
                        bar.setIndeterminate(true);
                    } else {
                        bar.setIndeterminate(false);
                        bar.setValue(progress);
                        progressDialog.dispose();
                    }
                }
            }
        });
        task.execute();
        progressDialog.setVisible(true);
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }
}

class Task extends SwingWorker<Void, Void> {

    private static final long SLEEP_TIME = 4000;
    private String text;

    public Task(String text) {
        this.text = text;
    }

    @Override
    public Void doInBackground() {
        setProgress(0);
        try {
            Thread.sleep(SLEEP_TIME);// imitate a long-running task
        } catch (InterruptedException e) {
        }
        setProgress(100);
        return null;
    }

    @Override
    public void done() {
        System.out.println(text + " is done");
        Toolkit.getDefaultToolkit().beep();
    }
}

关于java - 新线程 JDialog 中的 JProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11208660/

相关文章:

java - 获取 ArrayList 中的下一个值(不工作)

java - Eclipse WindowBuilder 在项目目录中生成 forms- 1.3.0.jar 和 miglayout15-swing.jar 文件

java - 来自 java 的异常 ": org.apache.hadoop.ipc.RpcException: RPC response exceeds maximum data length"

Java 2D 在图像上绘制和编辑对象并从图像中检测形状

java - Java Swing 的文本 API 是否适合显示自动生成的文本?

python 线程连接未正确发生

java - 从字符串中删除字符

C# 是否可以中断 ThreadPool 中的特定线程?

python - 在 Python 中捕获所有异常

java - 在 Swing 应用程序中仅显示一个选定或请求的 jpanel