【问题标题】:Progress Bar does not update Immediately进度条不会立即更新
【发布时间】:2013-09-15 15:39:07
【问题描述】:

我正在尝试使用进度条和标签来显示谨慎数量的操作的进度。每次我都更新时,标签会立即更新,而进度条在更改之前会有明显的延迟

我有一个测试对话框,当我按下按钮时,我会更新标签和进度条以反映增加 1。这会立即在代码中发生,而不会调用任何循环或线程(消除任何与线程相关的问题都是原因) - 只是简单地更改值。发生这种情况时,标签会立即更新,而进度条会等待大约半秒,然后再进行可视化更新。这会导致它会说,例如,“2 out of 3”,当它简短但明显地显示 1/3 条已填充时。

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class ProgressBarTest extends Shell {

    private ProgressBar progressBar;
    private Label lblXOfX;
    private Button btnGo;

    public static void main(String args[]) {
        try {
            Display display = Display.getDefault();
            ProgressBarTest shell = new ProgressBarTest(display);
            shell.open();
            shell.layout();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ProgressBarTest(Display display) {
        super(display, SWT.SHELL_TRIM);
        createContents();
    }

    protected void createContents() {
        setText("SWT Application");
        setSize(450, 300);
        setLayout(new GridLayout());

        progressBar = new ProgressBar(this, SWT.NONE);
        progressBar.setMaximum(3);
        progressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

        lblXOfX = new Label(this, SWT.NONE);
        lblXOfX.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
        lblXOfX.setText("x of x");

        btnGo = new Button(this, SWT.NONE);
        btnGo.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                go();
            }
        });
        btnGo.setText("Go");
    }

    @Override
    protected void checkSubclass() {
        // Disable the check that prevents subclassing of SWT components
    }

    protected void go() {

        int iCur = progressBar.getSelection();
        iCur++;
        if (iCur > progressBar.getMaximum())
            iCur = 0;

        progressBar.setSelection(iCur);
        lblXOfX.setText(String.format("%s of %s", iCur, progressBar.getMaximum()));
    }

}

尽管使用进度条的内部变量来跟踪值并使用该值更新标签,但仍会发生这种情况。

值得注意的是,将进度条的“状态”属性更改为“错误”或“暂停”可以消除此问题。

这是动画的某种错误吗? 这只是特定版本的 Windows 的问题,例如我使用的 Windows 7?还是别的什么?

【问题讨论】:

  • 很难用部分 sn-p 判断这里发生了什么——你能提供一个更完整的例子(我们可以自己编译和运行)来演示这个问题吗? (见sscce.org
  • @Chris 很好,完成了。
  • @Chris 我实际上可以让这更简单。我将重新处理整个问题。
  • 我猜它与 Windows 7 上 ProgressBar 中使用的动画有关,因为其他状态没有动画。此外,您的代码可以在 Linux 上完美运行。您可以发布错误报告here 让开发人员知道。
  • 在 Mac OS X 上也可以正常工作。ProgressBar.setSelection 的 Windows 版本确实有一些代码说它正在尝试处理一个听起来很像这样的问题,但只有在状态不正常 - 这可能是它在错误和暂停状态下工作的原因。他们的修复只是再次进行选择,所以也许调用 setSelection 两次会起作用!

标签: java windows swt progress-bar


【解决方案1】:

看起来这可能是 Windows 版本的 ProgressBar 中的一个错误,因为该代码适用于 Linux 和 Mac OS X。

ProgressBar.setSelection 的 Windows 版本确实有一些代码表示它正在尝试处理听起来像这样的问题,但只有在状态不正常时才会这样做 - 这可能是它在错误上起作用的原因和暂停状态。他们的修复只是再次进行选择,所以也许两次调用setSelection 会起作用!

【讨论】:

  • 我尝试连续两次执行 setSelection,但无济于事。这还有什么技巧吗?
【解决方案2】:

您可以关注this tutorial,它描述了如何制作 Eclipse 作业以便在 EDT 之外执行长作业,并仅更新组件的状态。 希望这会有所帮助,干杯!

【讨论】:

  • 本教程不太可能有帮助 - 除非另有说明,否则这不是由线程或缺少线程引起的。事实上,这里没有显示线程的原因是重点。如果您有其他感觉,请详细说明
【解决方案3】:

我已经在 Windows 7 SP 1 和 Windows XP SP3 下使用最新版本的 SWT(4.3 最终版本 - 2013 年 6 月 5 日)测试了您提供的代码。在这两种情况下,进度条都会立即更新。也许更新 SWT 库会有所帮助。

【讨论】:

    【解决方案4】:

    几周前我遇到了这个问题,当时我使用条形图显示连续完成约 500 次操作的进度。我发现这些过程在条形图还不到一半之前就已经完成了。我使用下面的代码作为解决方法:

    bargraph.value = (Target + 1)
    bargraph.value = (Target)
    

    bargraph 是您的对象的名称,target 是您希望它移动到的位置。

    由于条形图具有图形方面,即选框效果,因此需要时间才能赶上。 即使图形端可能显示值 50,实际 bargraph.value 可能是 60!通过将值设置为一个级别,然后将其减一,条形图会立即(ish)更新图形侧。

    编辑

    正如下面的评论所示,当您尝试将值设置为最大值时,上面的答案可能不起作用。

    现在,我还没有尝试过,但我认为下面的方法会起作用:

    if (bargraph.value <> Target) then
       if (Target = bargraph.maximumvalue) then
          bargraph.maximumvalue = Target + 1
          bargraph.value = (Target + 1)
          bargraph.value = (Target)
          bargraph.maximumvalue = Target
       else
          bargraph.value = (Target + 1)
          bargraph.value = (Target)
       end if
    else
    end if
    

    正如我所说,未经测试,但原理应该有效。

    【讨论】:

    • 嗯,是的,我也注意到了这一点。但是,这在 Target 为最大值的情况下是否有效?
    • 我不记得确切的错误,但我想您会收到类似于访问大小为 X 的数组的 X + 1 索引的错误。没有尝试过,但如果您尝试了上面的编辑,它可能会起作用
    猜你喜欢
    • 2018-11-08
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多