0

我在创建一个JProgressBar设置为不确定的时遇到问题。以下代码是我的实现,JProgressBar并从另一个类调用/构造:

public class Progress implements Runnable
{
  private JFrame frameProgress;
  private JProgressBar progressBar;

  public Progress(String title, String message)
  {
    try
    {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception e)
    {
      GlobalVariables.LOGGING_logger.error("Error instatiating progress bar.",
          e);
    }

    UIManager.put("ProgressBar.selectionForeground", Color.black);
    UIManager.put("ProgressBar.selectionBackground", Color.black);

    this.frameProgress = new JFrame(title);
    this.frameProgress.setIconImage(GlobalVariables.GUI_icon.getImage());
    this.frameProgress.setSize(300, 60);
    this.frameProgress.setLocation(16, 16);
    this.progressBar = new JProgressBar();
    this.progressBar.setStringPainted(true);
    this.progressBar.setString(message);
    this.progressBar.setIndeterminate(true);
    this.frameProgress.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.frameProgress.add(this.progressBar);
    this.frameProgress.setResizable(false);
    this.frameProgress.setVisible(true);
  }

  public void start()
  {
    new Thread(this).start();
  }

  public void close()
  {
    this.frameProgress.dispose();
    this.frameProgress = null;
    this.progressBar = null;
  }

  @Override
  public void run()
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        // do nothing, because progress bar is indeterminate
      }
    });
  }
}

这个 JProgressBar 的调用者是下面的代码片段:

    Progress p = new Progress("bla", "blub");
    p.start();
    boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this);
    p.close();

现在我希望xmlWriter.writeCommonSettingsFromGUI(this);在做某事的JProgressBar同时向用户显示并在算法运行时工作。

我怎样才能做到这一点?我不太了解线程和在许多其他论坛中搜索,但我没有找到任何问题的答案。

请帮助我,并提前谢谢你;)

编辑: Progress JFrame 打开时没有内容,算法正在运行。

4

1 回答 1

3

您可能正面临 Swing 的并发问题。假设以下代码在 EDT(事件调度线程)上运行:

Progress p = new Progress("bla", "blub");

最终,这将打开一个带有进度条的 JFrame。

  • 我会考虑使用 aJDialog而不是 aJFrame
  • 我不会强制的大小JFrame,而是调用pack()

然后,仍然在 EDT 上运行(并因此阻止所有 UI 事件,例如重绘、鼠标点击等),您调用p.start()which 启动一个new Thread()which 将调用run()which 本身调用

SwingUtilities.invokeLater(new Runnable()
{
  public void run()
  {
    // do nothing, because progress bar is indeterminate
  }
});

除了在 EventQueue 上推送一个附加事件之外,这基本上不会做任何事情,它将在所有当前未决事件之后运行。此事件将运行...“无”,因为您的 Runnable 只是空的。新线程几乎立即死亡。所以所有这些代码都是无用的。

您仍然在 EDT 上追求boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this);(顺便说一句,“成功”仅以一个“l”结尾)。这将继续阻塞 EDT,防止重绘发生并防止其JProgressBar本身进行绘制。最终您将处理 JFrame,但由于所有这些代码都在 EDT 上运行,用户将看不到太多进度条,并且 UI 看起来会冻结。

考虑阅读Swing 标签 wiki(尤其是最后一部分,其中包含 3 个重要链接)。

使用 aSwingWorker应该可以帮助您解决这个问题。

于 2013-04-11T09:40:06.690 回答