6

当长时间下载完成时,我只想在我的框架的左下角有一个不确定的 JProgressBar 动画。

我浏览了很多教程,其中没有一个对我来说很清楚。我只是想让它在后台下载文件时设置动画。我尝试过的每一种方式,在下载完成之前它都不会为进度条设置动画

我需要帮助知道在哪里放置我的 download() 调用。

class MyFunClass extends JFrame {
  JProgressBar progressBar = new JProgressBar();

  public void buttonClicked() {
    progressBar.setVisible(true);
    progressBar.setIndeterminate(true);

    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        progressBar.setIndeterminate(true);
        progressBar.setVisible(true);

        // Do I do my download() in here??

    }});

    // Do download() here???
    progressBar.setVisible(false);
  }
}

提前致谢!



解决方案

编辑:对于那些将来与我有类似问题的人,这是基本问题的基本解决方案。这不是我的逐字代码,而是一般草图。内部buttonClicked()

public void buttonClicked() {
  class MyWorker extends SwingWorker(String, Object) {
     protected String doInBackground() {
       progressBar.setVisible(true);
       progressBar.setIndeterminate(true);

       // Do my downloading code
       return "Done."
     }

     protected void done() {
        progressBar.setVisible(false)
     }
  }

  new MyWorker().execute();

}
4

1 回答 1

10

您当前的代码显示没有创建后台线程,而是显示您尝试从 Swing 线程中对 Swing 线程上的代码进行排队,这对这个问题没有意义(尽管有时您可能想要这样做这个,但同样,不是在这里)。成功的唯一方法是使用后台线程。标准的 Oracle JProgressBar 教程Swing 中的并发性贯穿了所有这些内容。

基本的事情是您必须从 Swing 线程更新 JProgressBar 将在后台线程中执行您的长时间运行的进程,例如 SwingWorker 对象提供的进程。有太多细节需要我们在这里查看,所以我所能做的就是提供一个链接,但是一旦你查看教程,我们很乐意帮助你理解细节。如果您仍然卡住,只需查看教程并返回您的具体问题。

编辑 1
您声明:

我可以在 buttonClicked() 函数中创建一个新的线程对象吗?

buttonClicked() 是的,您可以在方法内部创建一个 SwingWorker 对象并在那里执行它。

问题是我有我正在开发 GUI 的所有功能的 API 和库,将函数调用包装在线程中似乎是一个冗长的解决方法。

抱歉,但我不知道你在这里说什么或者你认为线程会导致什么问题。该buttonClicked()方法可能必须在 EDT 上而不是在后台线程中运行。

另请注意,在我的大多数更复杂的 Swing GUI 中,我经常在不同的(模型)对象中下载文件,并在与 GUI 对象(视图)不同的对象(控件)中创建我的 SwingWorker。这样做可能看起来更复杂,但是当我这样做时,调试、维护和增强我的程序容易得多,尤其是当我大量使用接口来允许我单独测试所有程序组件时。

编辑 2
对您的解决方案帖子的一些更正。您发布了:

public void buttonClicked() {
  class MyWorker extends SwingWorker(String, Object) {
     protected String runInBackground() {
       progressBar.setVisible(true);
       progressBar.setIndeterminate(true);

       // ...

哪个有问题

  • doInBackground(),不是runInBackground()
  • 但更重要的是,您是在后台线程中进行 Swing 调用,这是永远不应该做的事情(除非调用是线程安全的,即使那样......)。

所以改变它:

public void buttonClicked() {
  progressBar.setVisible(true);
  progressBar.setIndeterminate(true);
  class MyWorker extends SwingWorker<String, Void> {
     protected String doInBackground() {

       // ...
于 2012-05-04T03:48:19.380 回答