I try to do the following thing:
Add a component to a JFrame with a BorderLayout
Add another component to the JFrame
I would expect the new component to 'overwrite' the old component, since I'm using a BorderLayout. This works if I overwrite the old component before I call pack(). Now if I add the 2nd component after I call pack(), both components remain visible. Example:
public class Test extends JFrame{
public Test(){
setLayout(new BorderLayout());
add(new JLabel("Quite a long text"));
setVisible(true);
pack();
add(new JLabel("Another text"));
}
}
Result:
public class Test extends JFrame{
public Test(){
setLayout(new BorderLayout());
add(new JLabel("Quite a long text"));
setVisible(true);
add(new JLabel("Another text"));
pack();
}
}
Result:
I tried adding validate(); and repaint();, but that wouldn't help. What's going wrong here?
You are calling things that affect the UI after setViisble() is called -- a Swing no-no. Put things that affect the UI into an invokeLater call; look it up.
While you're at it, I think you're still supposed to get the content pane from the frame for adding components... And I don't think creating things in the constructor is a good idea.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class SwingTest extends JFrame
{
public void createUI()
{
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JLabel("Quite a long text"), BorderLayout.CENTER);
getContentPane().add(new JLabel("Another text"), BorderLayout.CENTER);
pack();
setVisible(true);
}
}
);
}
public static void main(String ... args)
{
SwingTest st = new SwingTest();
st.createUI();
}
}
Related
Following is the code in which the jbutton is not showing on the frame. I have also set visible to true. Even then the button doesn't appear.
class gui{
public static void main(String args[]){
layoutBorder lb=new layoutBorder("check");
}
}
class layoutBorder extends JFrame{
layoutBorder(String title){
super(title);
setLayout(null);
setSize(200, 200);
JButton jb=new JButton("JB");
add(jb);
setVisible(true);
}
}
Don't use a null layout!!!
Swing was designed to be used with layout managers.
Read the section from the Swing tutorial o Layout Managers for more information.
I suggest you download the working examples and play with them. The example will also show you how to better structure your code. Maybe start with the code from How to Use Buttons, which has a simple example that adds 3 buttons to a panel and then the panel to the frame.
Also, class names should start with an upper case character. Have you even seen a class in the API that doesn't??? Learn Java conventions and follow them.
camickr is right. Also, always use the AWT event dispatching thread when an application thread needs to update the GUI.
import javax.swing.*;
import java.awt.*;
import java.lang.*;
public class Gui {
public static void main(String args[]) {
SwingUtilities.invokeLater(() -> {
MyFrame frame = new MyFrame("check");
});
}
}
class MyFrame extends JFrame {
MyFrame(String title){
super(title);
setLayout(new BorderLayout());
setSize(200, 200);
JButton jb = new JButton("JB");
add(jb);
setVisible(true);
}
}
If you want null layouts then you need to set sizes and position by yourself. Using the setLocation and setSize methods.
class gui{
public static void main(String args[]){
layoutBorder lb=new layoutBorder("check");
}
}
class layoutBorder extends JFrame{
layoutBorder(String title){
super(title);
setLayout(null);
setSize(200, 200);
JButton jb=new JButton("JB");
jb.setLocation(10, 10);
jb.setSize(40, 30);
add(jb);
setVisible(true);
}
}
// This works!
JPanel background = new JPanel();
background.setBackground(Color.BLACK);
background.setBounds(0,0,this.getSize().width,this.getSize().height);
add(background);`
// Ihis method doesn't work! Why ? And the classic method setBackground(Color.BLACK); has the same problem
JPanel background = new JPanel()
{
#Override
public void setBackground(Color bg){
super.setBackground(Color.BLACK);
}
#Override
public void setBounds(int a, int b, int c, int d){
super.setBounds(0,0,this.getSize().width,this.getSize().height);
}
};
add(background);
Definite issue you are going to encounter will come from calling setBounds method.
Call setBackground for your panel and just add it to JFrame by calling add method. JPanel will be added on center of JFrame by default since default layout for JFrame is a BorderLayout and it will perfectly fit without of calling setBounds. There is absolutely no need to complicate things by overriding any method.
This:
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
JFrame frame = new JFrame();
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//frame.pack();
frame.setSize(400, 300);
frame.setVisible(true);
});
}
}
...will work perfectly.
Though you have ovverriden methods, you haven't called them.
I have a problem. Now I'm working with 3 panels, mainPanel and 2 others ( btnPanel and iconPanel).
So the problem is when I push button "reset" I delete iconPanel and add it again it moves slightly to right on its own. Maybe someone can check my code where the problem?
Also I dont want to create another question so I give 2 extra questions.
Do I delete JPanel properly?
If I delete JPanel with components inside they also will be removed from memory?
P.s. Im beginner so dont judge me :)
Main.java
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Made by Mac4s");
frame.setVisible(true);
frame.setSize(310, 654);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(false);
MainScreen screenObj = new MainScreen();
screenObj.setPreferredSize(new Dimension(310, 650));
frame.add(screenObj);
}
});
}
}
MainScreen.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class MainScreen extends JPanel {
private JButton resetBtn;
private JPanel btnPanel;
private JPanel iconPanel;
public MainScreen() {
JPanel mainPanel = new JPanel(new BorderLayout());
this.setBackground(Color.BLACK);
setBtnPanelAndComp();
setIconPanelAndComp();
add(mainPanel);
}
private void setBtnPanelAndComp() {
btnPanel = new JPanel(new BorderLayout());
btnPanel.setBackground(Color.GREEN);
btnPanel.setPreferredSize(new Dimension(295, 30));
setButtons();
this.add(btnPanel, BorderLayout.NORTH);
}
private void setButtons() {
resetBtn = new JButton("Reset");
resetBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
resetIconLabel();
}
});
btnPanel.add(resetBtn, BorderLayout.WEST);
}
private void resetIconLabel() {
this.remove(iconPanel);
this.repaint();
this.revalidate();
setIconPanelAndComp();
}
private void setIconPanelAndComp() {
iconPanel = new JPanel(new BorderLayout());
iconPanel.setBackground(Color.YELLOW);
iconPanel.setPreferredSize(new Dimension(295, 580));
this.add(iconPanel, BorderLayout.SOUTH);
}
}
"the problem is when I push button "reset" I delete iconPanel and add it again it moves slightly to right on its own."
The reason this happens is because a JPanel has a FlowLayout by default. You're trying add to a BorderLayout position that is non-existent.
this.add(iconPanel, BorderLayout.SOUTH);
The FlowLayout has default gaps on the edges, so when you set the size of the frame, those gaps aren't respected. To over come this, it is also preferable to pack() the frame, instead of setSize()
The reason BorderLayout works (doesn't shift) is because preferred sizes aren't respected.
If you set the layout in the constructor to this.setLayout(new BorderLayout()); You won't have the shift.
public MainScreen() {
JPanel mainPanel = new JPanel(new BorderLayout());
this.setLayout(new BorderLayout()); <----
setBtnPanelAndComp();
setIconPanelAndComp();
add(mainPanel);
}
Notes
You should setVisible() after adding components. That's why your frame jumps when you first open it. You are setting the frame visible, then moving it around with the location, and adding components.
Ok so im new to programming GUIs in Java and I need some help on how to add buttons and Labels. I went around looking at an example and I figured it this was how it worked to basically add a button:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GUI_Tests extends JFrame{
public static void main(String[] args){
private JButton button;
button = new JButton("pls work");
add(button);
}
}
Well that didnt work at all... Can someone show me how its done and give me some pointers?
You should note that a JFrame has a default BorderLayout which, if not specified, will add a component to a BorderLayout.CENTER position.
When adding components to JFrame, if a different Layout is not specified, then you want to set a component's position, like add(button, BorderLayout.SOUTH);
Also you should use a constructor. Something like this
public class GUI_Tests extends JFrame {
public GUI_Tests(){
JButton button = new JButton("Pls work");
JLabel label = new JLabel("Pls work");
add(button, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
}
}
Also you need to remember to set the frame visible.
A simple running program would be something like this
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class GUI_Tests extends JFrame {
public GUI_Tests() {
JButton button = new JButton("Pls work");
JLabel label = new JLabel("Pls work");
add(button, BorderLayout.CENTER);
add(label, BorderLayout.WEST);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new GUI_Tests();
}
});
}
}
The main method may look somewhat crazy to you, but all it is doing is causing the program to run on the Event Dispatch Thread (EDT). I won't go into this too much as you are still a beginner.
What is going on in the run is that all I do is create an instance of me program, which extends JFrame. If I didn't extend JFrame, I would have to explicitly create a JFrame to run the program. All GUI programs need some top-level container to run.
Also you can see in the constructor, that when I added the button and label I set a layout position
add(button, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
as I stated earlier, when using a JFrame without specifying a different layout, you should use position with the default `BorderLayout. Other possible positions are
BorderLayout.EAST
BorderLayout.WEST
BorderLayout.CENTER
BorderLayout.NORTH
BorderLayout.SOUTH
Take a look at [Laying Out Components Within a Container]Laying Out Components Within a Container)
Also, noticed I used pack(). What this does is make the frame the perfect with for the preferrsed sizes of the components. It is preferred to pack() rather then setSize() of a frame.
setDefaultCloseOperation(EXIT_ON_CLOSE); makes it so that when x out the frame, the program shuts down.
setLocationRelativeTo(null); set the frame's location in the center of the screen
setVisible(true); makes the frame visible. This should always be called to make the frame visible on start of the program.
Please have a look at the Swing tutorials
You are supposed to add your JButton to a JFrame, but it seems to me that you haven't even created a JFrame yet. You should first create an instance of GUI_Tests, then use the JFrame#add method with your JButton. For example:
public class GUI_Tests extends JFrame {
public GUI_Tests() {
super("My first Swing frame!");
this.setPreferredSize(new Dimension(640, 480));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create your GUI here
this.add(new JButton("Click on me :)"));
this.setVisible(true);
}
}
Actually, I wouldn't be mean to you, but I think you tried to go too fast: in my opinion, you should start by following some tutorial on how to deal with Swing :)
public class GUI_Tests extends JFrame {
private JButton button;
public GUI_Tests() {
setTitle("Title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // so that the application properly closes when you click close
button = new JButton("pls work");
add(button);
pack(); // resize the frame to its contents
setLocationRelativeTo(null); // center the frame on the screen
}
public static void main(String args[]) {
// properly start a swing application
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
GUI_Tests gui = new GUI_Tests();
gui.setVisible(true); // set the frame visible
}
});
}
}
hope this helps you understand it a bit more. i didn't use any layouts in this code as its just a simple example, however, i highly recommend you to read on built-in layouts in swing and how to use them.
Here's one good start
You need to add your button to a JFrame The basic flow should look something like this:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class GUITests extends JFrame{
public GUITests() {
setTitle("Simple example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton button = new JButton("pls work");
add(button);
pack();
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
GUITests ex = new GUITests();
ex.setVisible(true);
}
});
}
}
The GUITests class extends the JFrame class so you can call all the methods that are visible on the JFrame class. In the main method It's just some boiler plate code that calls your constructor for you so that you can see your basic example.
Check out the tutorials here: http://zetcode.com/tutorials/javaswingtutorial/firstprograms/
type
setVisible( true );
setSize( 500 , 500 );
and I think you'll see something. Also get rid of private in the statement private JButton button But you should really put your code in the constructor of the GUI_Tests:
import javax.swing.*;
public class GUI_Tests extends JFrame {
public GUI_Tests() {
JButton button = new JButton( "Hello World" );
add( button );
setVisible( true );
setSize( 500 , 500 );
}
final public static void main( String[] args ) {
GUI_Tests tests = new GUI_Tests();
}
}
Check out the Java tutorial for more help, possibly here: http://docs.oracle.com/javase/tutorial/uiswing/start/index.html
I know this is something very simple, but as a complete Java newbie I'm missing it and someone pointing it out would be infinitely helpful. I've stared at the screen and moved things around and still nothing.
Screenshot:
http://i.imgur.com/dwH60.png
This is all that comes up when this is run.
fullGUI.java:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
public class fullGUI extends JFrame
{
JFrame frame = new JFrame(); //creates frame
public fullGUI() // constructor
{
//setLayout(new BorderLayout());
//add(new shipGrid(), BorderLayout.NORTH);
//add(new shipGrid(), BorderLayout.NORTH);
add(new JRadioButton("Horizontal"), BorderLayout.WEST);
add(new JRadioButton("Vertical"), BorderLayout.WEST);
add(new JTextArea("Instructions to player will go here"), BorderLayout.CENTER);
frame.setSize(400,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Battleship!");
frame.pack(); //sets appropriate size for frame
frame.setVisible(true);
}
}
...called by...
test.java
public class test
{
public static void main(String[] args)
{
new fullGUI();
}
}
name classes in Java from a capital letter
FullGUI already extends JFrame, so no need to create another JFrame inside it
call getContentPane.add() to add to JFrame
use SwingUtilities.invokeLater
So overall something like this
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
public class FullGUI extends JFrame
{
public FullGUI() // constructor
{
getContentPane().add(new JRadioButton("Horizontal"), BorderLayout.WEST);
getContentPane().add(new JRadioButton("Vertical"), BorderLayout.WEST);
getContentPane().add(new JTextArea("Instructions to player will go here"), BorderLayout.CENTER);
setSize(400,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Battleship!");
pack(); //sets appropriate size for frame
setVisible(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new FillGU();
}
});
}
Problem is that you are extending JFrame in your class and creating new object "frame". You're adding components such as JRadioButton or JTextArea into fullGUI and other settings of the JFrame are applicable to frame object. It's up to you which approach you're going to choose, but pick one of them. You can extend JFrame and your class will be a child of JFrame which means you can call all public or protected methods from parent class, no need to create new instance of JFrame. Other way is to not extend JFrame and you have to create new JFrame object instead.
frame.pack() is causing your JFrame to resize according to its contents.
If you have frame.setSize(400,600), even if you don't add anything to its content pane,
the frame will be displayed with size 400x600.
But when you call frame.pack(), the frame will resize. In your case, your frame's content pane does not contain anything. Therefore the pack() method resizes it to only your title bar.
As Nikolay Kuznetsov said in earlier answer, you have extended Jframe in fullGUI so no need to create new Jframe in that class, because every instance of FullGUI will be a new frame.
With you code what happened is that you have created a Frame, say frame1 and instance of fullGUI(In main Method) say frame2, these are two different frames. In the Constructor you have added those controls to the frame2 (add()==this.add()) and said frame1.setvisible(true);
Adding controls to one frame and displaying altogether different frame is the reason why you were unable to see anything on output scree though you would have maximized the screen.