java - 让 ActionListener 在执行整个 ActionListener 之前向 JButton 提交更改

标签 java user-interface jbutton actionlistener

在 Java 中,我对 JButton 数组使用 ActionListener。我希望 ActionListener 的早期部分将新的 ImageIcon 设置为 JButton,该更改将立即显示,然后在 ActionListener 的末尾附近在第二个长时间延迟后将 JButton 的 ImageIcon 设置回 null。

我的问题是,在 ActionListener 完全完成之前,JButton 发生的任何更改都不会显示在设置它的 GUI 窗口中,从而使 JButton 的 ImageIcon 中的更改不明显。有没有办法让 ActionListener 在完成执行整个 ActionListener 之前向 JButton 提交更改,或者我应该以不同的方式处理此问题?

最佳答案

发生这种情况的原因:

Swing 在运行 ActionListener 时在同一线程 (EDT) 上重新绘制按钮。因此,如果它正在执行您的 ActionListener 它无法重新绘制,因为线程正忙 - 就这么简单。您可能已经注意到,当您的 Action 监听器正在执行时,您也无法正确移动框架等(GUI 卡住)。

解决方案:

将繁重的处理移至 EDT 之外。无论如何,它不属于那里。正如您可能已经猜到的 - 为此使用后台线程/线程池。一个很好的指南是 Swing tutorial for concurrency

注释:

如指南中所述,您不想修改 EDT 之外的组件。因此,最简单的策略是创建一个 Runnable 在后台线程上执行,启动它,更改按钮上的图片并返回,而无需等待任务完成。

public void actionPerformed(ActionEvent ae) {
    Runnable task = new Runnable() {..};
    executor.execute(task);
    button.setIcon(newIcon);
    return;
}

请注意,这不会锁定任务的 EDT,因此允许 Swing 立即更改图片。

这当然意味着用户不知道任务是否已完成(以及是否有任何异常)!毕竟它是在后台!因此,您的执行有一个额外的状态:GUI 响应且未卡住,按钮已更改,但任务仍在运行。在大多数应用程序中,这可能是一个问题(用户会向按钮发送垃圾邮件,或者您的后台任务可能会交错)。在这种情况下,您可能还想使用 SwingWorker 来获得“处理”状态。

public void actionPerformed(ActionEvent ae) {
    new TaskWorker().execute();
    button.setIcon(loadingIcon); //Shows loading. Maybe on button, maybe somewhere else.
    return;
}

private class TaskWorker extends SwingWorker<Void, T> {
    public Void doInBackground() {
        //Do your task in the background here
    }
    protected void done() {
        try {
            get();
            button.setIcon(doneIcon);
        catch (<relevant exceptions>) {
            button.setIcon(failedIcon);
        }
    }
}  

这里,当 doInBackground() 完成时,在 EDT 上调用 done()

关于java - 让 ActionListener 在执行整个 ActionListener 之前向 JButton 提交更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24435661/

相关文章:

java - Swing 中的注音假名(或 GUI 替代品……)

java - 如何给JButton设置图像图标?

java - Hibernate - 如何在不加载到内存的情况下删除条件?

java - Apache Commons Configuration2 如何从 InputStream 读取数据

java - 这个异常是什么意思?我该如何解决这个问题? java

java - 如何将 JButton 放置在 JTable 下?

Java 确定哪个文本字段具有焦点

java - Android java SELECT SQLite

c++ - 未绘制 QToolButton 上的文本

Java GUI 使用 setVisible()