首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重复执行SwingWorker

重复执行SwingWorker
EN

Stack Overflow用户
提问于 2012-05-05 09:24:49
回答 2查看 4.3K关注 0票数 0

我正在编写一个应用程序,做一些音频分析(作为一个吉他调谐器,加上和弦估计和其他一些东西),但我在GUI上遇到了一些问题。第一个问题是,我有一个按钮,点击应该改变其显示的文本。当点击文本时,文本不会改变,但是应该更改的代码行是绝对到达的。

另一件事是,我需要一个SwingWorker重复执行(一旦完成就重新启动),每次更新GUI。由于目前我的代码,我有一个while循环重复执行我的SwingWorker,但是这会导致GUI变得没有响应性,因为它在EDT中运行(大概)。让SwingWorker重复执行的最佳方法是什么?我应该创建一个新线程来运行循环,还是其他什么?

我的内部ActionListener类的代码如下:

代码语言:javascript
复制
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 ()方法中重新执行,但这似乎并没有真正帮助.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-05 11:42:25

声明:多线程并不是我最擅长的领域.

这两个问题实际上都是相同的,例如,由于EDT忙于运行while循环,您的GUI变得没有响应能力。这意味着它不能用新的文本值重新绘制按钮,也不能对用户的输入做出反应。

另外,SwingWorker的每个实例只能运行一次,因此在循环中多次调用execute()只能运行一次。

我建议创建一个TunerWorker对象并将循环放入其中,然后在需要启动循环时创建一个新的循环。如下所示:

代码语言:javascript
复制
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做什么,所以我把它从这个例子中拿出来了。希望这不会太难找到如何把它放回去。

编辑:哎呀,那个代码实际上不起作用。现在应该修好了。

票数 5
EN

Stack Overflow用户

发布于 2012-05-05 11:39:36

"SwingWorker只被设计为只执行一次。“相反,控制工人的执行和生命周期,如本示例所示。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10460495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档