我正在编写一个应用程序,做一些音频分析(作为一个吉他调谐器,加上和弦估计和其他一些东西),但我在GUI上遇到了一些问题。第一个问题是,我有一个按钮,点击应该改变其显示的文本。当点击文本时,文本不会改变,但是应该更改的代码行是绝对到达的。
另一件事是,我需要一个SwingWorker重复执行(一旦完成就重新启动),每次更新GUI。由于目前我的代码,我有一个while循环重复执行我的SwingWorker,但是这会导致GUI变得没有响应性,因为它在EDT中运行(大概)。让SwingWorker重复执行的最佳方法是什么?我应该创建一个新线程来运行循环,还是其他什么?
我的内部ActionListener类的代码如下:
private class TunerListener implements ActionListener {
private boolean firstUpdate = true;
private volatile boolean executing = false;
private final SwingWorker<Void, Void> tunerWorker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
model.update();
return null;
}
@Override
protected void done() {
if (!this.isCancelled()) {
prev.setText(model.getPrev());
currentNote.setText(model.getNote());
next.setText(model.getNext());
frequency.setText(model.getFrequency());
switch (model.getOffset()) {
case -2:
light_2.setIcon(onRed);
light_1.setIcon(off);
light0.setIcon(offBig);
light1.setIcon(off);
light2.setIcon(off);
break;
case -1:
light_2.setIcon(off);
light_1.setIcon(onRed);
light0.setIcon(offBig);
light1.setIcon(off);
light2.setIcon(off);
break;
case 0:
light_2.setIcon(off);
light_1.setIcon(off);
light0.setIcon(onGreen);
light1.setIcon(off);
light2.setIcon(off);
break;
case 1:
light_2.setIcon(off);
light_1.setIcon(off);
light0.setIcon(offBig);
light1.setIcon(onRed);
light2.setIcon(off);
break;
case 2:
light_2.setIcon(off);
light_1.setIcon(off);
light0.setIcon(offBig);
light1.setIcon(off);
light2.setIcon(onRed);
break;
}
}
}
};
@Override
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand().equals("tune")) {
if (!executing) {
tune.setText("Stop Tuning");
executing = true;
while (executing) {
tunerWorker.execute();
firstUpdate = false;
}
firstUpdate = true;
} else {
tune.setText("Start Tuning");
executing = false;
tunerWorker.cancel(true);
firstUpdate = true;
}
}
}
}编辑:按钮文本问题现在似乎已经解决了,但是我仍然不能让这个SwingWorker正常工作。我尝试完全删除while循环,并让它从to ()方法中重新执行,但这似乎并没有真正帮助.
发布于 2012-05-05 11:42:25
声明:多线程并不是我最擅长的领域.
这两个问题实际上都是相同的,例如,由于EDT忙于运行while循环,您的GUI变得没有响应能力。这意味着它不能用新的文本值重新绘制按钮,也不能对用户的输入做出反应。
另外,SwingWorker的每个实例只能运行一次,因此在循环中多次调用execute()只能运行一次。
我建议创建一个TunerWorker对象并将循环放入其中,然后在需要启动循环时创建一个新的循环。如下所示:
class TunerListener implements ActionListener {
private TunerWorker tw = null;
@Override
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand().equals("tune")) {
if (tw == null || tw.isDone()) {
tune.setText("Stop Tuning");
executing = true;
tw = new TunerWorker();
tw.execute();
} else {
tune.setText("Start Tuning");
executing = false;
tw.cancel(true);
}
}
}
}
final class TunerWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() {
while (!this.isCancelled()) {
model.update();
}
return null;
}
@Override
protected void done() {
if (!this.isCancelled()) {
//Removed this code to make the example prettier...
}
}
}哦,我不知道你想用firstUpdate做什么,所以我把它从这个例子中拿出来了。希望这不会太难找到如何把它放回去。
编辑:哎呀,那个代码实际上不起作用。现在应该修好了。
发布于 2012-05-05 11:39:36
"SwingWorker只被设计为只执行一次。“相反,控制工人的执行和生命周期,如本示例所示。
https://stackoverflow.com/questions/10460495
复制相似问题