簡體   English   中英

重復執行SwingWorker

[英]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.

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