【问题标题】:Java Swing Threading with Updatable JProgressBar带有可更新 JProgressBar 的 Java Swing 线程
【发布时间】:2011-03-02 04:47:14
【问题描述】:

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

  • 有一个具有SplashScreen 的应用程序在加载信息时暂停
  • 能够在SplashScreen下运行多个线程
  • SplashScreen 的进度条可以更新,但在所有线程完成之前不会退出。

启动闪屏

try {
    SwingUtilities.invokeAndWait( SplashScreen );
} catch (InterruptedException e) {
} catch (InvocationTargetException e) { }

闪屏搭建

SplashScreen extends JFrame implements Runnable{

    public void run() {
        //run threads
        //while updating status bar
    }
}

我尝试了很多东西,包括SwingWorkers、使用 CountDownLatch 的线程等等。 CountDownLatch 实际上以我想要处理的方式工作,但我无法更新 GUI。使用SwingWorkers 时,invokeAndWait 基本上无效(这是他们的目的),或者即使使用PropertyChangedListener 也不会更新GUI。如果其他人有一些想法,很高兴听到它们。提前致谢。

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

【问题讨论】:

  • 如果您可以创建并发布SSCCE,您的问题可能会得到更快、更正确的解决。
  • 抱歉,我在发帖时正在睡觉,我所发布的代码非常丑陋,所以我希望能传达这个想法,如果下面的答案对我不起作用,我'会发布一些真实的代码。谢谢推荐。

标签: java multithreading swing concurrency swingworker


【解决方案1】:

要在后台运行一系列操作并报告进度,请使用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
        }
    }
};

附录:

这可以扩展到多个任务,它只需要更改设置进度条的方式。以下是我想到的:

有一个完成计数器数组,每个任务一个。

int[] completions = new int[numTasks];
Arrays.fill(completions,0);

启动 SwingWorkers,每个都传递一个索引号。然后processdone 方法调用类似这样的方法来更新整体进度条。

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

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

附录 2:

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

【讨论】:

  • 这似乎行不通我需要多个摇摆工作人员,他们仍然会继续执行下一个代码,这就是为什么我提到了 invokeAndWait() 方法,因为我需要它等等,我需要多个 SwingWorker 运行,我不想在所有工作人员完成之前继续。
【解决方案2】:

不需要在invokeAndWait中调用框架,但你应该像这样更新进度条状态。

try {
   SwingUtilities.invokeAndWait( new Runnable() {
     public void run() {
//update state of the progress bar here
     }
   });
 } catch (InterruptedException e) {
 } catch (InvocationTargetException e) { }

【讨论】:

  • 谢谢,我试试看是否有帮助。
  • 我不能让它与线程或 SwingWorkers 一起工作,我正在用一些更好的代码更新我的问题。感谢您迄今为止的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
相关资源
最近更新 更多