簡體   English   中英

Eclipse“Widget被丟棄”錯誤

[英]Eclipse “Widget is disposed” Error

好吧所以我在這里使用Eclipse Oxygen(我認為這很重要,因為它看起來像是Eclipse生成的錯誤)。 我已經在這個特定錯誤上看過其他幾篇帖子,但是這些帖子都沒有為我工作/不是我已經嘗試過的東西。 所以我的目標是有一個while循環並讓它每秒獲得db聲級並更新標簽。

不幸的是,這連續5次不起作用。 第一個,窗口沒有打開,我意識到這是因為while循環使窗口保持打開狀態,所以我將它放入一個線程中。 然后就像5次嘗試稍后修復它一樣,我的代碼中仍然出現“Widget was dispos”錯誤。 這是打開窗口的代碼(這是我創建項目以來唯一改變的代碼):

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)

PS最后一行錯誤說34是該函數的調用者,第一行是進度條更改行。 有任何想法嗎?

Shell窗口僅在while (!shlAudioAdjuster.isDisposed())循環運行時顯示。 一旦該循環退出,shell中的所有控件都將被丟棄並且不能再使用。 所以你不能把你的代碼放在循環之后。

您必須將播放聲音的代碼放在打開shell時啟動的單獨線程中。 但是您無法直接在后台線程中更新進度條,而是需要使用Display.asyncExec在UI線程中運行進度條更新:

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

您可能還想檢查進度條是否已被釋放並停止該線程:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM