Java JButton setEnabled失效:跨类调用无法启用按钮求助
问题描述
我有一个默认设置为setEnabled(false)的JButton,当另一个类的条件为true时希望启用该按钮,但按钮始终无法启用。所有三个类属于同一包。直接在主方法调用setButtonEnabled()能正常启用按钮,请问这是为什么?该如何解决?
涉及代码
Main.java(主类)
import javax.swing.JFrame; public class Main { public static void main(String[] args) { JFrame frame = new JFrame(); OtherClass c1 = new OtherClass(); Panel p = new Panel(); frame.add(p); frame.setSize(300,300); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); //p.setButtonEnabled(); } }
Panel.java
import javax.swing.JButton; import javax.swing.JPanel; public class Panel extends JPanel{ JButton b1 = new JButton("OK"); ; public Panel(){ b1.setSize(50, 50); b1.setEnabled(false); add(b1); } public void setButtonEnabled(){ b1.setEnabled(true); } }
OtherClass.java
public class OtherClass { Panel p1 = new Panel(); //some method public void method(){ if (true){ p1.setButtonEnabled(); } } }
原因分析
核心问题是你创建了两个完全独立的Panel对象:
- Main类中创建的
Panel p是被添加到JFrame、显示在界面上的实例; - OtherClass里的
Panel p1是全新的独立实例,它和界面上的Panel没有任何关联。调用p1.setButtonEnabled()只是启用了这个看不见的Panel里的按钮,界面上的按钮自然不会有变化。
解决方法
方法一:传递界面实例给OtherClass(推荐)
修改OtherClass,去掉内部的Panel实例,通过构造方法接收主类中创建的、用于界面显示的Panel:
public class OtherClass { private Panel p1; // 构造方法接收外部的Panel实例 public OtherClass(Panel panel) { this.p1 = panel; } public void method(){ if (true){ p1.setButtonEnabled(); } } }
修改Main类,创建OtherClass时传入那个被添加到窗口的Panel:
public static void main(String[] args) { JFrame frame = new JFrame(); Panel p = new Panel(); // 传入界面上的Panel实例 OtherClass c1 = new OtherClass(p); frame.add(p); frame.setSize(300,300); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); // 调用method即可启用界面上的按钮 c1.method(); }
方法二:使用全局静态实例(简单场景适用)
修改Panel类,添加一个静态实例,保证程序中只有一个Panel对象:
import javax.swing.JButton; import javax.swing.JPanel; public class Panel extends JPanel{ JButton b1 = new JButton("OK"); // 静态实例,全局唯一 public static Panel instance; public Panel(){ instance = this; b1.setSize(50, 50); b1.setEnabled(false); add(b1); } public void setButtonEnabled(){ b1.setEnabled(true); } }
修改OtherClass,直接调用全局静态实例的方法:
public class OtherClass { public void method(){ if (true){ Panel.instance.setButtonEnabled(); } } }
Main类无需额外修改,只要创建过Panel,静态实例就会被赋值,调用OtherClass的method即可生效。
额外提示
Swing的UI操作应该放在**事件调度线程(EDT)**中执行,规范写法如下:
import javax.swing.SwingUtilities; import javax.swing.JFrame; public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame(); Panel p = new Panel(); OtherClass c1 = new OtherClass(p); frame.add(p); frame.setSize(300,300); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); c1.method(); }); } }
内容的提问来源于stack exchange,提问作者aegold
相关产品推荐
相关产品推荐

