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 ?
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.
JButton(String text) This constructor will create a button in the component with the specified text in the parameters.
In Swing, classes that represent GUI components have names beginning with the letter J. Some examples are JButton, JLabel, and JSlider.
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
}
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With