java - eclipse "Widget is disposed"错误

标签 java eclipse swt

好吧,我在这里使用 Eclipse Oxygen(我认为这很重要,因为它看起来像是 Eclipse 生成的错误)。我看过其他几篇关于这个特定错误的帖子,但没有一篇对我有用/这不是我已经尝试过的事情。所以我的目标是有一个 while 循环并让它每秒获取 db 声级并更新标签。

不幸的是,这并没有像连续 5 次那样奏效。首先,窗口没有打开,我意识到这是因为 while 循环阻止了窗口打开,所以我把它放到了一个线程中。然后像 5 次尝试修复它一样,我的代码中仍然出现“Widget is disposed”错误。这是打开窗口的代码(这是我创建项目后唯一更改的代码):

public void open() throws InterruptedException, LineUnavailableException {
    Display display = Display.getDefault();
    shlAudioAdjuster = new Shell();
    shlAudioAdjuster.setSize(450, 300);
    shlAudioAdjuster.setText("Audio Adjuster");

    Label lblCurrentDecibelLevel = new Label(shlAudioAdjuster, SWT.NONE);
    lblCurrentDecibelLevel.setFont(SWTResourceManager.getFont("Muli", 14, SWT.NORMAL));

    ProgressBar progressBar = new ProgressBar(shlAudioAdjuster, SWT.NONE);
    progressBar.setSelection(30);
    progressBar.setBounds(143, 168, 170, 17);
    shlAudioAdjuster.open();
    shlAudioAdjuster.layout();
    while (!shlAudioAdjuster.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
    AudioFormat audioFormat = getAudioFormat();
    TargetDataLine targetDataLine;
    try {
        targetDataLine = (TargetDataLine) AudioSystem.getTargetDataLine(audioFormat);
        targetDataLine.open();
        targetDataLine.start();
        byte [] buffer = new byte[2000];
        while (true) {
            int bytesRead = targetDataLine.read(buffer,0,buffer.length);
             int max;
             if (bytesRead >=0) {
                 max = (short) (buffer[0] + (buffer[1] << 8));
                 for (int p=2;p<bytesRead-1;p+=2) {
                     short thisValue = (short) (buffer[p] + (buffer[p+1] << 8));
                     if (thisValue>max) max=thisValue;
                 }
                 progressBar.setSelection((int)(20 * Math.log10(max)));
             }
        }
    } catch (LineUnavailableException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

错误确认 progressBar.setSelection((int)(20 * Math.log10(max))); 存在问题。这是完整的错误:

org.eclipse.swt.SWTException: Widget is disposed
    at org.eclipse.swt.SWT.error(SWT.java:4533)
    at org.eclipse.swt.SWT.error(SWT.java:4448)
    at org.eclipse.swt.SWT.error(SWT.java:4419)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:482)
    at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:354)
    at org.eclipse.swt.widgets.ProgressBar.setSelection(ProgressBar.java:322)
    at MainWindow.open(MainWindow.java:90)
    at MainWindow.main(MainWindow.java:34)

P.S 错误的最后一行说 34 是该函数的调用者,第一行是进度条更改行。有什么想法吗?

最佳答案

Shell 窗口仅在 while (!shlAudioAdjuster.isDisposed()) 循环运行时显示。一旦该循环退出,shell 中的所有控件都将被丢弃并且不能再使用。所以你不能把你的代码放在那个 while 循环之后。

您必须将播放声音的代码放在打开 shell 时启动的单独线程中。但是您不能直接在后台线程中更新进度条,而是需要使用 Display.asyncExec 在 UI 线程中运行进度条更新:

Display.getDefault().asyncExec(() -> progressBar.setSelection((int)(20 * Math.log10(max))));

您可能还想检查进度条是否已被处理并停止线程:

if (progressBar.isDisposed()) {
  // TODO exit the thread
}

关于java - eclipse "Widget is disposed"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51867793/

相关文章:

java - Android 应用程序解析 JSON 数据错误?

java - eclipse 添加未实现的方法,包括 javadoc

java - 以编程方式将现有项目导入 Eclipse

java - 如何将tableviewer的内容保存到swt中的文本文件中

java - 虚拟表和 ViewerComparator 上的默认排序问题

java - 带圆角的 SWT 外壳

java - 在 Java 中使用嵌套 for 循环查找概率

java - Eclipse WTP 与 sydeo, "serves modules without publishing "

eclipse - 使用Gradle buildship Eclipse插件找不到调试选项

java - 如何在mongodb中动态添加现有嵌套文档中的文档