java - 在构造函数外使用 .setVisible() 会破坏我的 GUI

标签 java swing user-interface jframe multiple-instances

我刚刚在学习 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 类,它将作为您的 JFramesetVisble(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(..)

这是您的代码,其中包含上述修复:

enter image description here

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/

相关文章:

java - 带有 httpclient 4.5.3 的 GZIP

java - 从 Java 使用 POST 发送文件

Java Swing : how to know the state of the mouse from outside the component receiving the event?

java - 在 swing 中向现有表添加一列

c++ - 如何获取Qt C++中所有可用主题的列表?

java - setLineNumber面临的问题

java - 使用 ActionBinding 按下组合键

java - 使用 Java 制作 GUI 从哪里开始(Swing 是否已弃用?)

c++ - 可执行文件无法正常工作 [Linux]

java - Servlet 不工作