Eclipse "Widget is disposed" 错误
Eclipse "Widget is disposed" Error
好的,所以我在这里使用 Eclipse Oxygen(我认为这很重要,因为它看起来像是 Eclipse 生成的错误)。我看过其他几篇关于此特定错误的帖子,但其中 none 对 me/weren 没有我已经尝试过的事情有效。所以我的目标是有一个 while 循环并让它每秒获取 db 声级并更新标签。
不幸的是,这并没有像连续 5 次那样奏效。首先,window 没有打开,我意识到这是因为 while 循环阻止了 window 打开,所以我把它放到了一个线程中。然后像 5 次尝试修复它一样,我的代码中仍然出现 "Widget is disposed" 错误。这是打开 window 的代码(这是我创建项目后唯一更改的代码):
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 window 仅在 while (!shlAudioAdjuster.isDisposed())
循环为 运行ning 时显示。一旦该循环退出,shell 中的所有控件都将被处理掉并且不能再使用。所以你不能把你的代码放在 while 循环之后。
您必须将播放声音的代码放在打开 shell 时启动的单独线程中。但是不能直接在后台线程中更新进度条,需要在UI线程中使用Display.asyncExec
到运行进度条更新:
Display.getDefault().asyncExec(() -> progressBar.setSelection((int)(20 * Math.log10(max))));
您可能还想检查进度条是否已处理并停止线程:
if (progressBar.isDisposed()) {
// TODO exit the thread
}
好的,所以我在这里使用 Eclipse Oxygen(我认为这很重要,因为它看起来像是 Eclipse 生成的错误)。我看过其他几篇关于此特定错误的帖子,但其中 none 对 me/weren 没有我已经尝试过的事情有效。所以我的目标是有一个 while 循环并让它每秒获取 db 声级并更新标签。
不幸的是,这并没有像连续 5 次那样奏效。首先,window 没有打开,我意识到这是因为 while 循环阻止了 window 打开,所以我把它放到了一个线程中。然后像 5 次尝试修复它一样,我的代码中仍然出现 "Widget is disposed" 错误。这是打开 window 的代码(这是我创建项目后唯一更改的代码):
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 window 仅在 while (!shlAudioAdjuster.isDisposed())
循环为 运行ning 时显示。一旦该循环退出,shell 中的所有控件都将被处理掉并且不能再使用。所以你不能把你的代码放在 while 循环之后。
您必须将播放声音的代码放在打开 shell 时启动的单独线程中。但是不能直接在后台线程中更新进度条,需要在UI线程中使用Display.asyncExec
到运行进度条更新:
Display.getDefault().asyncExec(() -> progressBar.setSelection((int)(20 * Math.log10(max))));
您可能还想检查进度条是否已处理并停止线程:
if (progressBar.isDisposed()) {
// TODO exit the thread
}