【问题标题】:Using .setVisible() outside the constructor breaks my GUI在构造函数之外使用 .setVisible() 会破坏我的 GUI
【发布时间】:2013-01-30 12:14:03
【问题描述】:

我现在正在学习 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
}

为什么会这样?

在这个例子中没关系,但是如果我想让一个窗口只有在我点击一个按钮或其他东西时才可见怎么办?

【问题讨论】:

    标签: java swing user-interface jframe multiple-instances


    【解决方案1】:

    1) 您创建了JFrame 的 2 个实例,第一个实例来自在类上扩展 JFrame,第二个实例来自 JFrame window=..。然后您继续在window 上拨打setVisible(..) 并尝试在您的dogYears 上拨打setVisible(...)

    解决方案

    您应该只为每个 Swing GUI 创建一个JFrame。摆脱extends JFrame(以及随之而来的代码),因为在Swing 中扩展JFrame 并不是一个好习惯。因此,您当然不能在构造函数中调用 setVisible(true),这可以在构造函数中创建 GUI 之后调用它,或者在 GUI 类中创建类似 setVisible 的方法,这将是您的 JFrames 的包装器setVisble(boolean b) 方法。

    其他建议

    • 始终在 Event Dispatch Thread 上创建您的 Swing 组件,您应该通过 SwingUtilitites.invokeLater(Runnable r) 块来执行此操作。阅读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
                }
            });
        }
    }
    

    【讨论】:

    • 是的,所有最初都是在几分钟内输入的,彼此 +1 用于扩展 :-)
    • 是的,@kleo 刚才所说的同上。 1+
    • @DavidKroukamp 我刚刚找到了这个很好的答案,我有一个问题,你说“在 EDT 上创建组件”,所以我必须在 Runnable 中完成所有工作还是仅例如调用方法 setVisible(true)?
    【解决方案2】:

    你有两个JFrames,GUI 类本身和内部变量“window”。只使用一个。

    确保 GUI 不扩展 JFrame(不需要这样做),并为类提供一个 public void setVisible(boolean) 方法,将窗口设置为可见。

    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();
    
        public GUI () {
    
            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 void setVisible(boolean visible) {
            window.setVisible(visible);
        }
    }
    

    【讨论】:

    • +1 哦,HFOE 在做我的时候从来没有看到这个答案。伟大的思想都一样:P。
    • @Kalec:如果在 GUI 类的构造函数本身中不调用 pack() 方法,您确实是正确的。
    • @HovercraftFullOfEels 你的setVisible(boolean visible) 不会编译,因为你的JFrame - window 没有在范围内声明。编辑您的代码以反映正确的更改(将 JFrame 声明移至全局)
    【解决方案3】:

    你有两个不同的实例:-)

    在你的构造函数中:

    JFrame window = new JFrame();
    window.setVisible(true); // IF IT'S HERE IT WORKS
    

    在你的主要:

    GUI dogYears = new GUI();
    dogYears.setVisible(true); 
    // dogYears != local var window in constructor
    

    这可能让我开始扩展类,而是使用它们。

    【讨论】:

    • 它让 开始了。 1+
    • 那么如果我想setVisible in,就说main。我必须创建一个函数 getWindow 吗?将 that 设置为可见?还是包装方法?
    • 是的,这可能有效,但是如果你不将它用作 JFrame,为什么 GUI 会扩展 JFrame,另请参阅 EventDispatch 帖子并使用 SwingUtilitites.invokeLater(Runnable r)
    • lol +1 在我开始做我的工作时从未见过所有这些帖子。 +1 这是问题
    【解决方案4】:

    您的类 GUI 扩展自 JFrame,但在构造函数中,您正在初始化另一个 JFrame,这会导致 两个不同的 JFrames .

    试试这个:

    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!");
    
        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);
        }
    
        // main
    
    }
    

    【讨论】:

      【解决方案5】:

      您正在 GUI 的构造函数中创建 JFrame 的实例,该实例也扩展了 JFRame。 现在您正在创建不同的组件并将它们添加到“窗口”对象上。 如您所知,框架设置为可见 = 假和未装饰 = 假。 因此,要设置特定的 JFrame 实例,您需要在该实例上调用 setVisible() 方法。

      在这里,您只是创建了一个 GUI 实例,并没有在其上添加任何组件。 在构造函数中编写如下语句,而不是 "window.setContentPane(content);":

      setContentPane(内容);

      然后在您的 GUI 类实例上调用 setVisible() 方法,即 d*ogYears.setVisible(true);*!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-14
        • 2018-02-20
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        • 1970-01-01
        • 2010-10-08
        相关资源
        最近更新 更多