Eclipse "Widget is disposed" Error

tdog :

Alright so I'm using Eclipse Oxygen here (I think that's important since it looks like this is an Eclipse-generated error). 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.

Unfortunately, that didn't work like 5 times in a row. 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. And then like 5 attempts to fix it later, I'm still getting a "Widget is disposed" error in my code. 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)));. 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)

P.S The last line of error saying 34 is the caller for that function, the first is the progress-bar-change line. Any ideas?

greg-449 :

The Shell window is only displayed while the while (!shlAudioAdjuster.isDisposed()) loop is running. Once that loop has exited all the controls in the shell are disposed and cannot be used anymore. 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. 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.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
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=104637&siteId=1