我刚刚在学习 Java GUI 的基础知识。我有这种奇怪的情况,我真的无法解释。
我有一个 GUI 类,我在其中构建了一个简单的 JFrame。如果我使用 .setVisible(true)
在构造函数中 一切正常,如果我在外部 使用它,没有加载(窗口可见,但按钮和其他不可见)。
为什么会这样?
public class GUI extends JFrame {
private JTextField humanYears_TextField = new JTextField(3);
private JTextField dogYears_TextField = new JTextField(3);
private JButton convert_Button = new JButton("Convert");
private JLabel greeting = new JLabel ("Dog years to Human years!");
public GUI () {
JFrame window = new JFrame();
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(this.greeting);
content.add(new JLabel("Dog Years: "));
content.add(this.dogYears_TextField);
content.add(this.convert_Button);
content.add(new JLabel("Human Years: "));
content.add(this.humanYears_TextField);
window.setContentPane(content);
pack(); // aplica contentPane-ul
window.setLocationRelativeTo(null);
window.setTitle("Dog Year Converter");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true); // IF IT'S HERE IT WORKS
}
}
public static void main(String[] args) {
GUI dogYears = new GUI();
//dogYears.setVisible(true); // IF IT'S HERE
//NOTHING EXCEPT THE WINDOW LOADS
}
为什么会这样?
在这个例子中它并不重要,但是如果我想让一个窗口只有在我点击一个按钮或其他东西时才可见怎么办?
最佳答案
1) 您创建了 JFrame
的 2 个实例,第一个来自类上的扩展 JFrame
,第二个来自 JFrame window=..
。你不是继续在 window
上调用 setVisible(..)
并且在你的主要尝试调用 setVisible(...)
你的 dogYears
。
解决方案
您应该只为每个 Swing GUI 创建一个 JFrame
。去掉 extends JFrame
(以及随之而来的代码),因为在 Swing 中扩展 JFrame
不是好的做法。因此,您当然无法在构造函数中调用 setVisible(true)
,这很好,要么在构造函数中创建 GUI 后调用它,要么在中创建类似 setVisible
的方法GUI 类,它将作为您的 JFrame
的 setVisble(boolean b)
方法的包装器。
其他建议
始终在
Event Dispatch Thread
上创建您的 Swing 组件,您应该在SwingUtilitites.invokeLater(Runnable r)
block 中执行此操作。阅读 Concurrency in Swing .请记住在设置
JFrame
可见之前和添加组件之后调用 pack。setLocationRelativeTo(..)
应该在pack()
之后。除非使用计时器,否则最好使用
JFrame.DISPOSE_ON_CLOSE
。也不需要
setContentPane
,只需在JFrame
实例上调用add(..)
。
这是您的代码,其中包含上述修复:
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class GUI {
private JTextField humanYears_TextField = new JTextField(3);
private JTextField dogYears_TextField = new JTextField(3);
private JButton convert_Button = new JButton("Convert");
private JLabel greeting = new JLabel("Dog years to Human years!");
private JFrame window = new JFrame();
private JPanel content = new JPanel();
public GUI() {
content.setLayout(new FlowLayout());
content.add(this.greeting);
content.add(new JLabel("Dog Years: "));
content.add(this.dogYears_TextField);
content.add(this.convert_Button);
content.add(new JLabel("Human Years: "));
content.add(this.humanYears_TextField);
window.add(content);
window.setTitle("Dog Year Converter");
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.pack();
window.setLocationRelativeTo(null);
//window.setVisible(true); //works here now
}
//our wrapper method so we can change visibility of our frame from outside the class
void setVisible(boolean visible) {
window.setVisible(visible);
}
public static void main(String[] args) {
//Create Swing components on EDT
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
GUI dogYears = new GUI();
dogYears.setVisible(true);//works here too
}
});
}
}
关于java - 在构造函数外使用 .setVisible() 会破坏我的 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14603762/