使用可更新JProgressBar的Java Swing线程

ars*_*265 2 java concurrency swing multithreading swingworker

首先,我最近一直在使用Java的Concurrency软件包,但我发现了一个问题,我被困在了.我想拥有和应用程序和应用程序可以有SplashScreen一个状态栏和其他数据的加载.所以我决定使用SwingUtilities.invokeAndWait( call the splash component here ).在SplashScreen随后与出现JProgressBar并运行一组线程.但我似乎无法很好地处理事情.我已经查看SwingWorker并尝试将其用于此目的,但线程只是返回.这是一些伪代码.以及我正在努力实现的目标.

  • SplashScreen在加载信息时有一个暂停的应用程序
  • 能够在下运行多个线程 SplashScreen
  • SplashScreenUpdate-able 的进度条在所有线程完成之前都不会退出.

启动启动画面

try {
    SwingUtilities.invokeAndWait( SplashScreen );
} catch (InterruptedException e) {
} catch (InvocationTargetException e) { }
Run Code Online (Sandbox Code Playgroud)

飞溅屏幕结构

SplashScreen extends JFrame implements Runnable{

    public void run() {
        //run threads
        //while updating status bar
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了很多东西,包括SwingWorkers使用CountDownLatch的Threads等等.CountDownLatch实际上以我想要处理的方式工作但我无法更新GUI.当使用SwingWorkers任一invokeAndWait已基本作废(这是他们的目的),或者使用时,它不会甚至仍在更新GUI PropertyChangedListener.如果其他人有一些想法,那么听听他们会很棒.提前致谢.

我实际上准备好发布更好的代码来帮助我找到我的解决方案.感谢所有帮助过的人.

Dev*_*ler 5

要在后台运行一系列操作并报告进度,请使用SwingWorker.

background方法进行后台处理.
使用该publish方法发布定期状态更新.
覆盖process方法以处理更新(process始终在EDT上执行).

progressBar = new JProgressBar();
sw = new SwingWorker<Boolean,Integer>() {
    protected Boolean doInBackground() throws Exception {
        // If any of the operations fail, return false to notify done() 
        // Do thing 1
        publish(25);  // 25% done
        // Do thing 2
        publish(50);  // 50% done
        // Do thing 3
        publish(75);  // 75% done
        // Do thing 4
        return true;
    }
    protected void process(List<Integer> chunks) {
        for (Integer i : chunks)
            progressBar.setValue(i);
    }
    protected void done() {
        try {
            boolean b = get();
            if (b)
                progressBar.setValue(100); // 100% done
            else
                // Notify the user processing failed
        }
        catch (InterruptedException ex) {
                // Notify the user processing was interrupted
        }
        catch (ExecutionException ex) {
                // Notify the user processing raised an exception
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

附录:

这可以扩展到多个任务,只需要更改设置进度条的方法.这就是我想到的:

有一个完成计数器阵列,每个任务一个.

int[] completions = new int[numTasks];
Arrays.fill(completions,0);
Run Code Online (Sandbox Code Playgroud)

启动SwingWorkers,每个都传递一个索引号.该processdone方法,然后调用这样的更新总体进度条.

void update(int index, int percComplete) {
    completions[index] = percComplete;
    int total = 0;
    for(int comp: completions)
        total += comp/numTasks;
    overallPB.setValue(total);
}
Run Code Online (Sandbox Code Playgroud)

(可选)为每个任务显示JProgressBar.

附录2:

如果任务的完成时间不同(例如,缓存命中与缓存未命中),您可能需要调查ProgressMonitor.这是一个进度对话框,仅当任务需要超过一些(可配置的,默认的500毫秒)时间时才会出现.