带 Swing 进度条的多线程

Multi threading with Swing progress bar

我运行不知道如何在执行 RMI 连接期间使我的进度条响应,所以我决定向您寻求帮助。

代码如下:

Thread performLogin = new Thread(new Runnable()
{

    @Override
    public void run()
    {
        LoginResult = TryLogin();
    }
});

performLogin.start();
WaiterFrame.setVisible(true);
SetProgressDialog();

try
{
    performLogin.join();
}
catch(InterruptedException exc)
{
    System.err.println(exc.getLocalizedMessage());
}

if (LoginResult)
{ ... }


WaiterFrame.setVisible(false);
this.dispose();

进度条没有响应 - 在执行 performLogin 线程时没有按应有的动画显示。我也在另一个线程上尝试 运行 进度条框架,但结果是一样的(以及使用 Eventqueue.invokelater())。

如果您使用的是 Java 8,您可以尝试这样的操作:

CompletableFuture<LoginResult> loginResult = CompletableFuture.supplyAsync(this::tryLogin);
WaiterFrame.setVisible(true);
setProgressDialog();
loginResult.thenAccept(lr -> {
   //do your thing 
   WaiterFrame.setVisible(false); 
})

"thenAccept" 还有其他选项,具体取决于您需要执行的操作。 "thenAccept" 只消费 Future 的内容。

如果 Java 8 不是一个选项,则可以使用 Guava 的 ListenableFuture 和 Executors 来完成同样的事情。

可能的原因是 performLogin.join(); 阻塞了事件调度线程,导致 UI 无响应。

使用 Swing(以及大多数 GUI 框架)要记住两件事;

  1. 它是单线程的,这意味着如果您出于任何原因阻止 EDT,它将不再能够处理新事件或执行重绘
  2. 它不是线程安全的,所以你不应该从 EDT 上下文之外修改 UI 的状态。

您可以使用 SwingWorker,这将允许您在后台线程中 运行 您的长 运行ning 进程,但提供了多种机制,您可以通过这些机制发送更新安全返回美国东部时间。

请参阅 Worker Threads and SwingWorker for more details and Issues with SwingWorker and JProgressBar 示例

非常感谢 MadProgrammer!进度条按预期与 SwingWorker 一起使用。如果有人将来会鼓励同样的问题,我会发布代码:

PerformLogin = new SwingWorker<Boolean, Object>()
{
    @Override
    protected Boolean doInBackground() throws Exception
    {
        LoginResult = TryLogin();
        if (LoginResult)
        {
            MainF = new MainFrame();
            MainF.Connection = DataEntry.TestConnection;
            MainF.prepareFormToShow();
        }
        return LoginResult;
    }

    @Override
    protected void done()
    {
        if (LoginResult == true)
        {
            EventQueue.invokeLater(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        MainF.setVisible(true);
                        WaiterFrame.setVisible(false);
                    }
                });
        }
        else
        {
            setVisible(true);
            this.cancel(true);
            JOptionPane.showMessageDialog(null, "Wrong adress!",
            "Błąd",JOptionPane.WARNING_MESSAGE);
        }
    }

WaiterFrame.setVisible(true);
PerformLogin.execute();

在主线程中