简体   繁体   English

Eclipse“Widget被丢弃”错误

[英]Eclipse “Widget is disposed” Error

Alright so I'm using Eclipse Oxygen here (I think that's important since it looks like this is an Eclipse-generated error). 好吧所以我在这里使用Eclipse Oxygen(我认为这很重要,因为它看起来像是Eclipse生成的错误)。 I've seen several other posts on this specific error, but none of them worked for me/weren't things I had already tried. 我已经在这个特定错误上看过其他几篇帖子,但是这些帖子都没有为我工作/不是我已经尝试过的东西。 So my goal is to have a while loop and have it get the db sound level every second and update a label. 所以我的目标是有一个while循环并让它每秒获得db声级并更新标签。

Unfortunately, that didn't work like 5 times in a row. 不幸的是,这连续5次不起作用。 The first, the window didn't open, and I realized it was because the while loop was keeping the window from opening, so I put it into a thread. 第一个,窗口没有打开,我意识到这是因为while循环使窗口保持打开状态,所以我将它放入一个线程中。 And then like 5 attempts to fix it later, I'm still getting a "Widget is disposed" error in my code. 然后就像5次尝试稍后修复它一样,我的代码中仍然出现“Widget was dispos”错误。 Here's the code for opening the window (that's the only code I've changed since I made the project): 这是打开窗口的代码(这是我创建项目以来唯一改变的代码):

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();
    }
}

And the error confirms there is a problem with progressBar.setSelection((int)(20 * Math.log10(max))); 并且错误确认progressBar.setSelection((int)(20 * Math.log10(max))); . Here's the full error: 这是完整的错误:

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)

PS The last line of error saying 34 is the caller for that function, the first is the progress-bar-change line. PS最后一行错误说34是该函数的调用者,第一行是进度条更改行。 Any ideas? 有任何想法吗?

The Shell window is only displayed while the while (!shlAudioAdjuster.isDisposed()) loop is running. Shell窗口仅在while (!shlAudioAdjuster.isDisposed())循环运行时显示。 Once that loop has exited all the controls in the shell are disposed and cannot be used anymore. 一旦该循环退出,shell中的所有控件都将被丢弃并且不能再使用。 So you can't put your code after that while loop. 所以你不能把你的代码放在循环之后。

You will have to put the code playing the sound in a separate thread which you start when you open the shell. 您必须将播放声音的代码放在打开shell时启动的单独线程中。 But you can't update the progress bar directly in a background thread, instead you need to use Display.asyncExec to run the progress bar update in the UI thread: 但是您无法直接在后台线程中更新进度条,而是需要使用Display.asyncExec在UI线程中运行进度条更新:

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

You might also want to check if the progress bar has been disposed and stop the thread: 您可能还想检查进度条是否已被释放并停止该线程:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM