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

Kal*_*lec 5 java user-interface swing multiple-instances jframe

我刚刚学习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
}
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

在这个例子中它并不重要,但是如果我只想点击一个按钮或什么东西我想让窗口可见呢?

Dav*_*amp 6

1)您可以在类上创建JFrame 第一个第一个实例,JFrame第二个来自JFrame window=...你不是去上调用setVisible(..)window,并在你的主,你尝试调用setVisible(...)你的dogYears.

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

其他建议

  • 始终Event Dispatch Thread在via SwingUtilitites.invokeLater(Runnable r)块中创建Swing组件.阅读Swing中的Concurrency.

  • 请记住在设置JFrame可见之前和添加组件之后调用pack .

  • setLocationRelativeTo(..)应该来pack().

  • JFrame.DISPOSE_ON_CLOSE除非使用Timers,否则最好使用.

  • 也没有必要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
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,所有人最初都是在几分钟之内输入+1以进行扩展:-) (2认同)

Hov*_*els 5

你有两个JFrame,GUI类本身和内部变量"窗口".只使用一个.

确保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);
    }
}
Run Code Online (Sandbox Code Playgroud)