swing:单击时禁用make按钮

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

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

  1. import javax.swing.*;
  2. import java.awt.event.ActionEvent;
  3. import java.awt.event.ActionListener;
  4. public class Example extends JFrame implements ActionListener {
  5. public static void main(String[] args) {
  6. Example e = new Example();
  7. e.setVisible(true);
  8. }
  9. private JButton button;
  10. public Example() {
  11. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  12. this.setSize(600, 400);
  13. this.setLayout(null);
  14. button = new JButton("button");
  15. button.setBounds(200, 150, 200, 50);
  16. button.addActionListener(this);
  17. this.add(button);
  18. }
  19. @Override
  20. public void actionPerformed(ActionEvent actionEvent) {
  21. button.setEnabled(false);
  22. try {
  23. Thread.sleep(5000);
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }

问题是,我们有 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 :

  1. import java.awt.BorderLayout;
  2. import javax.swing.*;
  3. import java.awt.event.ActionEvent;
  4. import javax.swing.border.EmptyBorder;
  5. public class Example {
  6. private JButton button;
  7. private Timer timer;
  8. public static void main(String[] args) {
  9. SwingUtilities.invokeLater(Example::new);
  10. }
  11. public Example() {
  12. JFrame frame = new JFrame();
  13. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  14. JPanel panel = new JPanel();
  15. panel.setBorder(new EmptyBorder(20, 20, 20, 20));
  16. button = new JButton("button");
  17. button.addActionListener((ActionEvent e) -> {
  18. if (timer != null && timer.isRunning()) {
  19. return;
  20. }
  21. button.setEnabled(false);
  22. timer = new Timer(5000, (ActionEvent e1) -> {
  23. // TODO do something after sleeping for 5 seconds
  24. button.setEnabled(true);
  25. timer.stop();
  26. });
  27. timer.start();
  28. });
  29. panel.add(button, BorderLayout.CENTER);
  30. frame.add(panel);
  31. frame.pack();
  32. frame.setVisible(true);
  33. }
  34. }
展开查看全部
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);
}

  1. private JButton button;
  2. public Example() {
  3. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  4. this.setSize(600, 400);
  5. this.setLayout(null);
  6. button = new JButton("button");
  7. button.setBounds(200, 150, 200, 50);
  8. button.addActionListener(this);
  9. this.add(button);
  10. }
  11. @Override
  12. public void actionPerformed(ActionEvent actionEvent) {
  13. button.setEnabled(false);
  14. startThread();
  15. }
  16. private void startThread() {
  17. SwingWorker sw1 = new SwingWorker() {
  18. @Override
  19. protected Object doInBackground() {
  20. try {
  21. Thread.sleep(5000);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. return null;
  26. }
  27. @Override
  28. protected void done() {
  29. button.setEnabled(true);
  30. }
  31. };
  32. sw1.execute();
  33. }

}

展开查看全部

相关问题