Reputation: 2881
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 ?
Upvotes: 5
Views: 4649
Reputation: 285405
You've got two JFrame
s, the GUI class itself and the internal variable "window". Use only one.
Make sure that GUI does not extend JFrame
(there's no need for this), and give the class a public void setVisible(boolean)
method that sets the window to visible.
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);
}
}
Upvotes: 5
Reputation: 36423
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 JFrame
s 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:
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
}
});
}
}
Upvotes: 7
Reputation: 22997
Your class GUI
extends from a JFrame
, but in the constructor, you are initializing another JFrame, which results in having two different JFrame
s.
Try this:
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
}
Upvotes: 2
Reputation: 123
you are creating an instance of JFrame in constructor of GUI which also extends JFRame. Now you are creating different components and added them on 'window' object. As you know a frame is set as visible= false and undecorated=false. So to set a particular JFrame instance you need to call setVisible() method on that instance.
Here you are just creating an instance of GUI and didn't added any component on it. write a statement in constructor as following rather than "window.setContentPane(content);":
setContentPane(content);
and then call setVisible() method on your instance of GUI class i.e d*ogYears.setVisible(true);*!!
Upvotes: 0
Reputation: 51525
You have two different instances :-)
in your constructor:
JFrame window = new JFrame();
window.setVisible(true); // IF IT'S HERE IT WORKS
in your main:
GUI dogYears = new GUI();
dogYears.setVisible(true);
// dogYears != local var window in constructor
Which might get me starting on not extending classes, but using them.
Upvotes: 4