【问题标题】:Repeated execution of SwingWorkerSwingWorker的重复执行
【发布时间】:2012-05-05 09:24:49
【问题描述】:

我正在编写一个应用程序来进行一些音频分析(用作吉他调音器,并添加和弦估计和其他一些东西),但我在使用 GUI 时遇到了一些问题。第一个问题是我有一个按钮,单击该按钮应更改其显示的文本。单击时,文本没有改变,但肯定到达了应该改变它的代码行。

另一件事是我需要一个 SwingWorker 来重复执行(完成后重新启动)并每次更新 GUI。正如我目前的代码一样,我有一个循环重复执行我的 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() 方法中重新执行,但这似乎并没有帮助...

【问题讨论】:

  • 最好为每个问题单独提出一个问题
  • 但是......在这种情况下,问题似乎是一样的。
  • 您能详细说明一下吗?我发现这真的不像我期望的那样工作:(
  • 我正在写一个答案:)

标签: java swing jbutton execute swingworker


【解决方案1】:

SwingWorker 仅设计为执行一次。”而是控制 worker 的执行和生命周期,如 example 所示。

【讨论】:

    【解决方案2】:

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

    你的两个问题实际上是一回事,例如您的 GUI 变得无响应,因为 EDT 正忙于运行 while 循环。这意味着它不能用新的文本值重绘按钮,也不能对用户输入做出反应。

    另外,每个 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 做什么,所以我把它从示例中删除了。希望弄清楚如何将其放回原处不会太难。

    编辑:哎呀,该代码实际上并没有工作。现在应该修好了。

    【讨论】:

    • +1 用于缩小焦点; GUI 可以从process() 安全更新。
    • +1 表示Also, each instance of a SwingWorker can only be run once, so calling execute() several times in a loop only runs it once.。这就是我一直在寻找的。​​span>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多