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

时间:2013-01-30 12:14:04

标签: 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
}

为什么会这样?

在这个例子中没关系,但是如果我只想点击一个按钮或什么东西就可以看到一个窗口怎么办?

5 个答案:

答案 0 :(得分:6)

1)您可以在课程中扩展JFrame,从JFrame扩展JFrame window=..,创建第一个setVisible(..)个实例。您继续拨打window上的setVisible(...),然后在您的dogYears上尝试拨打JFrame

<强>解决方案

您应该只为每个Swing GUI创建一个extends JFrame。摆脱JFrame(以及随之而来的代码),因为在Swing中扩展setVisible(true)是不好的做法。因此,您当然无法在构造函数中调用setVisible,无论是在构造函数中创建GUI之后调用它还是在GUI类中创建类似JFrame的方法,它将是您的包装器setVisble(boolean b) Event Dispatch Thread方法。

其他建议

  • 始终在SwingUtilitites.invokeLater(Runnable r)上创建您应该通过JFrame块执行的Swing组件。阅读Concurrency in Swing

  • 请务必在设置setLocationRelativeTo(..)之前和添加组件后调用包。

  • pack()应该在JFrame.DISPOSE_ON_CLOSE之后。

  • 除非使用计时器,否则最好使用setContentPane

  • 也不需要add(..)只需在JFrame个实例上拨打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 } }); } }

以下是您的代码,其中包含上述修复程序:

enter image description here

{{1}}

答案 1 :(得分:5)

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

确保GUI不扩展JFrame(不需要这样做),并为该类提供一个公共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);
    }
}

答案 2 :(得分:4)

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

在你的构造函数中:

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

哪些可能让我开始而不是扩展类,但使用它们。

答案 3 :(得分:2)

您的班级GUI来自JFrame,但在构造函数中,您正在初始化另一个JFrame,这导致两个不同 JFrame 取值

试试这个:

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

}

答案 4 :(得分:0)

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

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

setContentPane(内容);

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