swing:单击时禁用make按钮

63lcw9qa  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(424)

我正在编写一段代码,我准备了一个简单的示例:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Example extends JFrame implements ActionListener {
    public static void main(String[] args) {
        Example e = new Example();
        e.setVisible(true);
    }

    private JButton button;

    public Example() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(600, 400);
        this.setLayout(null);

        button = new JButton("button");
        button.setBounds(200, 150, 200, 50);
        button.addActionListener(this);
        this.add(button);
    }
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        button.setEnabled(false);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

问题是,我们有 actionPerformed 函数,它有两个操作:禁用按钮并运行 sleep 模仿我做的一些工作。
我的问题是那个按钮在 actionPerformed 结束,所以换句话说,在这5秒钟的睡眠之后,我不能更早地禁用它。我试着用它做些什么,但到目前为止改变了 button.setEnabled(false);button.setEnabled(false); this.repaint(); this.validate(); 什么都不做。
我的问题是:如何在swing中执行作业,首先需要禁用按钮,然后执行一些耗时的操作(例如睡眠)并在作业完成时启用按钮?

lp0sw83n

lp0sw83n1#

那是因为你不能 Thread.sleep() 在同一个线程上创建ui,否则它将冻结ui直到睡眠结束。
你想做的可能是使用一个swing计时器或者swing worker。
其他一些要点:
不要延伸 JFrame 不必要地上课
不要使用null/ AbsoluteLayout 而是使用适当的布局管理器
不要打电话 setBounds() 或者 setSize() 在组件上,如果使用正确的布局管理器,这将为您处理
呼叫 JFrame#pack() 在将框架设置为可见之前
所有swing组件都应该通过 SwingUtilities.invokeLater 我也从来不喜欢实施 ActionListener 在类的基础上,特别是如果您将有一个以上的组件注册 ActionListener .
下面是使用 Timer :

import java.awt.BorderLayout;
import javax.swing.*;
import java.awt.event.ActionEvent;
import javax.swing.border.EmptyBorder;

public class Example {

    private JButton button;
    private Timer timer;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Example::new);
    }

    public Example() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setBorder(new EmptyBorder(20, 20, 20, 20));

        button = new JButton("button");

        button.addActionListener((ActionEvent e) -> {
            if (timer != null && timer.isRunning()) {
                return;
            }

            button.setEnabled(false);

            timer = new Timer(5000, (ActionEvent e1) -> {
                // TODO do something after sleeping for 5 seconds
                button.setEnabled(true);
                timer.stop();
            });
            timer.start();
        });

        panel.add(button, BorderLayout.CENTER);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}
6yjfywim

6yjfywim2#

@大卫·克鲁坎普非常感谢,这就是我要找的。如果有人需要这里是简单的(但不是完美的,见托达维德的答案)的例子 Worker ```
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Example extends JFrame implements ActionListener {
public static void main(String[] args) {
Example e = new Example();
e.setVisible(true);
}

private JButton button;

public Example() {
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(600, 400);
    this.setLayout(null);

    button = new JButton("button");
    button.setBounds(200, 150, 200, 50);
    button.addActionListener(this);
    this.add(button);
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
    button.setEnabled(false);
    startThread();
}

private void startThread() {

    SwingWorker sw1 = new SwingWorker() {
        @Override
        protected Object doInBackground() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void done() {
            button.setEnabled(true);
        }
    };

    sw1.execute();
}

}

相关问题