[英]Repeated execution of SwingWorker
我正在編寫一個進行音頻分析的應用程序(用作吉他調音器,並增加了和弦估計等功能),但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循環,並使其從它的done()方法重新執行,但這似乎並沒有幫助。
“ SwingWorker
僅設計為只能執行一次。” 相反,如本示例所示,控制工作人員的執行和生命周期。
免責聲明:多線程不是我最擅長的領域...
您的兩個問題實際上是同一回事,例如,由於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
做什么,所以我從示例中firstUpdate
了它。 希望弄清楚如何重新安裝它不會太難。
編輯:糟糕,該代碼實際上不起作用。 現在應該修復。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.