【问题标题】:Why do my changes in ActionListener not take effect immediately?为什么我对 ActionListener 的更改没有立即生效?
【发布时间】:2015-01-13 10:51:36
【问题描述】:

这是我的代码:

public MyClass() {
    JButton btnNext;
    private void initComponents() {
        btnNext = new javax.swing.JButton();
        btnNext.setText("Lanjut");
        btnNext.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNextActionPerformed(evt);
            }
        });
    }

    private void btnNextActionPerformed(java.awt.event.ActionEvent evt) {
        btnNext.setText("Loading...");
        callingFunction();
    }
}

注意:callingFunction() 是一个需要很长时间才能执行的函数。

我的问题是我的按钮文本只有在 callFunction() 完成后才会变为“正在加载...”。

如何立即将 btnNext 文本更改为“正在加载...”?

【问题讨论】:

  • 我认为它类似于 btnNext.revalidate();虽然我不确定。但最好的方法是在单独的线程中完成你的功能
  • 不要阻塞 EDT(事件调度线程)。发生这种情况时,GUI 将“冻结”。有关详细信息和修复,请参阅 Concurrency in Swing
  • 为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)。
  • @WhiteNightFury 谢谢,但这不适合我

标签: java swing concurrency awt actionlistener


【解决方案1】:

在控制权返回到 Swing 事件队列之前,不会重新绘制按钮。在事件调度线程上调用该函数会阻塞事件队列。

作为一种解决方法,告诉它稍后运行该函数(一旦完成重新绘制):

在 Java 8+ 中:

EventQueue.invokeLater(() -> callingFunction());

在旧 Java 中:

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        callingFunction();
    }
});

请注意,这仍然会产生副作用,即在该函数运行时阻止与 GUI 的进一步交互。如果您想在后台线程中运行长任务以保持 GUI 交互,请使用SwingWorker。一个最小的例子,假设callingFunction 返回一些你想用来更新显示的String(或其他)类型的结果:

new SwingWorker<String,Void>() {
    @Override
    protected String doInBackground() throws Exception {
        // called on a background thread
        return callingFunction();
    }

    @Override
    protected void done() {
        // called on the event dispatch thread after the work is done
        String result;
        try {
            result = get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // do something with the result ...
        someTextField.setText(result);
    }
}.execute();

【讨论】:

  • 在 SwingWorker 中我如何调用我当前的类?,即当没有 SwingWorker 时,我可以在 callFunction() 中使用“this”
  • @Tama 将 this.foo 更改为 ClassName.this.foo
  • 在最后一行我得到了这个错误不兼容的类型:void 不能转换为 SwingWorker 我怎么了?
  • 代码太长,我用了EventQueue,它的工作。非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多