5

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

为什么会这样?

在此示例中,这无关紧要,但是如果我想让窗口仅在单击按钮或其他内容时才可见怎么办?

4

5 回答 5

7

1)您创建 2 个实例,JFrame 第一个实例来自扩展JFrame类,第二个实例来自JFrame window=... 然后你继续调用并且setVisible(..)window你的主中你尝试调用setVisible(...)你的dogYears.

解决方案

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

其他建议

  • 始终创建您Event Dispatch Thread应该在 viaSwingUtilitites.invokeLater(Runnable r)块中执行的 Swing 组件。阅读Swing 中的并发

  • JFrame记得在设置可见之前和添加组件之后调用 pack 。

  • 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
            }
        });
    }
}
于 2013-01-30T12:22:16.537 回答
5

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

确保 GUI 没有扩展JFrame(不需要这样做),并为类提供一个公共的 voidsetVisible(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);
    }
}
于 2013-01-30T12:23:18.107 回答
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

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

于 2013-01-30T12:22:45.220 回答
2

您的类GUI从 a 扩展JFrame,但在构造函数中,您正在初始化另一个 JFrame,这导致有两个不同 JFrame的 s

试试这个:

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

}
于 2013-01-30T12:25:23.793 回答
0

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

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

设置内容窗格(内容);

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

于 2013-01-30T12:38:18.543 回答