Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using .setVisible() outside the constructor breaks my GUI

I am just now learning the basics of java GUI. I have this weird situation that I can't really explain.

I have a GUI class, where I build a simple JFrame. If I use .setVisible(true) within the constructor everything works fine, if I use it outside, nothing loads (the window is visible, but the buttons and what not aren't).

Why is this happening ?

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
}

Why is this happening ?

In this example it doesn't matter, but what if I want to make a window visible only if I click a button or something ?

like image 340
Kalec Avatar asked Jan 30 '13 12:01

Kalec


People also ask

What is the purpose of setVisible ()?

The default size of a frame is 0 by 0 pixels. The setVisible(true) method makes the frame appear on the screen. If you forget to do this, the frame object will exist as an object in memory, but no picture will appear on the screen.

What happens when the constructor JButton string msg is called?

JButton(String text) This constructor will create a button in the component with the specified text in the parameters.

Which classes represent GUI components have names beginning with the letter J?

In Swing, classes that represent GUI components have names beginning with the letter J. Some examples are JButton, JLabel, and JSlider.


1 Answers

1) You create 2 instances of JFrame the first from extending JFrame on the class and the second from JFrame window=... You than go on to call setVisible(..) on the window and in your main you attempt to call setVisible(...) on your dogYears.

Solution

You should only create one JFrame per Swing GUI. Get rid of the extends JFrame (and the code that goes with it), as its not good practice to extend JFrame in Swing. Thus of course you wont be able to call setVisible(true) in your constructor which is fine either call it after creating the GUI in the constructor or make a method like setVisible in GUI class which will be a wrapper for your JFrames setVisble(boolean b) method.

Other suggestions

  • Always create your Swing components on the Event Dispatch Thread which you should do in via SwingUtilitites.invokeLater(Runnable r) block. Have a read on Concurrency in Swing.

  • Remember to call pack before setting JFrame visible and after adding components.

  • setLocationRelativeTo(..) should come after pack().

  • Better to use JFrame.DISPOSE_ON_CLOSE unless using Timers.

  • Also no need for setContentPane simply call add(..) on JFrame instance.

Here is your code with above mentioned fixes:

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
            }
        });
    }
}
like image 193
David Kroukamp Avatar answered Sep 23 '22 23:09

David Kroukamp