Java Component alignment to top left corner - java

I want to align my two of my components to the top left corner of the window.
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
public class MainFrame extends JFrame {
public MainFrame() {
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel gridbagPanel = new JPanel();
this.setLayout(new BorderLayout());
gridbagPanel.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
JLabel nameLabel = new JLabel(player.getName());
nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
nameLabel.setFont(new Font("Serif",Font.PLAIN,24));
mainPanel.add(nameLabel, BorderLayout.NORTH);
JLabel money = new JLabel("Pinigai: "+new Integer(player.getMoney()).toString());
gc.gridx = 0;
gc.gridy = 0;
gc.anchor = GridBagConstraints.PAGE_START;
gc.insets = new Insets(2,0,0,2);
gridbagPanel.add(money,gc);
JLabel job = new JLabel("Darbas: "+new Integer(player.getSkin()).toString());
gc.gridx = 0;
gc.gridy = 1;
gc.insets = new Insets(2,0,0,2);
gc.anchor = GridBagConstraints.LINE_START;
gridbagPanel.add(job, gc);
mainPanel.setBorder(new EmptyBorder(10,10,10,10));
mainPanel.add(gridbagPanel,BorderLayout.WEST);
add(mainPanel);
getContentPane().revalidate();
}
}
It currently looks like this:
And I would like the lines with numbers in the top left corner.
Note that I'm aware that both JFrame("this" class) and the mainPanel are using BorderLayouts.
Another non-related question: When should I create a new GridBagConstraints object? Why can't I just store one in a private instance variable for all usage needed?

The beauty of GridBagLayout, is that column/row sizes are not fixed (ie, not every row/column has to be the same size, like in GridLayout)
You can "encourage" certain components to occupy more space within their given area then others.
Things like weightx and weighty describe how much of the available space a row/column should occupy. Add in the NORTHWEST anchor constraint and you should begin to see the desired effect.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class MainFrame extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new MainFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public MainFrame() {
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel gridbagPanel = new JPanel();
this.setLayout(new BorderLayout());
gridbagPanel.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
JLabel nameLabel = new JLabel("Bebras");
nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
nameLabel.setFont(new Font("Serif", Font.PLAIN, 24));
mainPanel.add(nameLabel, BorderLayout.NORTH);
JLabel money = new JLabel("Pinigai: " + new Integer(66484).toString());
gc.gridx = 0;
gc.gridy = 0;
gc.anchor = GridBagConstraints.NORTHWEST;
gc.insets = new Insets(2, 0, 0, 2);
gridbagPanel.add(money, gc);
JLabel job = new JLabel("Darbas: " + new Integer(126).toString());
gc.gridx = 0;
gc.gridy = 1;
gc.insets = new Insets(2, 0, 0, 2);
gc.anchor = GridBagConstraints.NORTHWEST;
gc.weightx = 1;
gc.weighty = 1;
gridbagPanel.add(job, gc);
mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
mainPanel.add(gridbagPanel, BorderLayout.WEST);
add(mainPanel);
getContentPane().revalidate();
}
}
Normally, I would add a "filler" component into the component, using it to push all the other components to where I want them, but this will come down to what it is you want to achieve.
Take a look at How to use GridBagLayout for more details

Im more of a fan of Box Layouts to achieve this type of static positioning in swing. see the example below:
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class main extends JFrame {
public static void main(String[] args) throws InterruptedException {
main m = new main();
m.setVisible(true);
}
public main() {
// setup stuff
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setBounds(100, 100, 500, 500);
// this is the panel I will add to the frame
JPanel innerPanel = new JPanel();
// give it a Y axis to stuff is added top to bottom
innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.Y_AXIS));
// this is a temp panel ill used to add the labels
JPanel tPanel = new JPanel();
// its an x axis to add stuff left to right
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
// create and add a label to the temp panel
JLabel label = new JLabel("Some text");
tPanel.add(label);
// use our stretchy glue to fill the space to the right of the label
tPanel.add(Box.createHorizontalGlue());
// add the temp panel to the inner panel
innerPanel.add(tPanel);
// create a spacer with 0 width and 10 height
innerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
// reinitialize the temp panel for another label
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
label = new JLabel("Some other text");
// add the other label to the temp panel
tPanel.add(label);
// more stretchy glue
tPanel.add(Box.createHorizontalGlue());
// add the temp panel
innerPanel.add(tPanel);
// add verticle stretchy glue to fill the rest of the space below the
// labels
innerPanel.add(Box.createVerticalGlue());
// add to the frame
this.add(innerPanel);
}
}

Related

Position a JButton properly within a GridBagLayout | Java 8

I want to position a JButton "Start" in the lower center of my GUI.
Sadly the GridBagConstraints that I set seem to have no effect.
I'm working with jdk1.8.0_191 and the Eclipse IDE.
EDIT: I switched my snippet to a "minimal reproducible example".
Here the snippet of my code:
package gui.main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test{
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(646, 509);
frame.setResizable(false);
frame.setTitle("Adventure Time");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 5;
JButton button = new JButton("Start");
button.setBackground(Color.black);
button.setForeground(Color.white);
button.setPreferredSize(new Dimension(110, 60));
button.setMinimumSize(new Dimension(110, 60));
button.setVisible(true);
panel.add(button, gbc);
panel.setVisible(true);
frame.add(panel);
frame.setVisible(true);
}
}
Here is a picture where I approximately want the "Start" Button instead.
I created a simple, runnable example of a GUI with a start button on the lower fourth of the JPanel. Here's the example GUI.
Use Swing components. Don't extend Swing components, or any other Java class, unless you intend to override one of the methods in the class.
I used a BorderLayout for the JPanel. I used a calculated empty border to shift the start button down from the center.
I set the size of the JPanel in this example. I'm assuming you'll set the size of the game panel based on the size of your image.
Here's the code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class StartButtonExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new StartButtonExample());
}
#Override
public void run() {
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
Dimension panelSize = new Dimension(400, 400);
panel.setPreferredSize(panelSize);
JButton button = new JButton("Start");
Dimension buttonSize = button.getPreferredSize();
int height = panelSize.height - buttonSize.height;
int width = panelSize.width - buttonSize.width;
int top = height * 3 / 4;
int left = (width - buttonSize.width) / 2;
int bottom = height / 4;
int right = left;
panel.setBorder(BorderFactory.createEmptyBorder(
top, left, bottom, right));
panel.add(button, BorderLayout.CENTER);
return panel;
}
}
In my amateurish opinion:
I ended up using different insets for my small application.
It is more clean looking in my opinion.
//margin 400 top, rest 3
gbc.insets = new Insets(400,3,3,3);
gbc.gridy = 0;
getWrapperPanel().add(getBtnStart02(), gbc);
//margin 3 at all sides for all following gui objects
gbc.insets = new Insets(3,3,3,3);
gbc.gridy = 1;
getWrapperPanel().add(getBtnLoad(), gbc);
Works like a charm.

How to change JPlane position?

I tried create some window application. I have container which consist a JFrame and two JPanel (white square and red square. The last square inside white square).
I want change position red square ( any place on my work window( for example, left or right side)). I tried do it, but i didn't have success.
Could you help me?
It's my code)
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class main_window extends JFrame {
public static void main(String\[\] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.black);
frame.getContentPane().setLayout(new GridLayout(1, 1));
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
JPanel panel_1 = new JPanel();
panel_1.setPreferredSize(new Dimension(200, 200));
panel_1.setBackground(Color.red);
panel.add(panel_1);
frame.setSize(800,800);
frame.setVisible(true);
}
}
GridBagLayout will give you the greatest amount of control over the layout itself.
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.WHITE);
setLayout(new GridBagLayout());
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
pane.setBackground(Color.RED);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
// Left
//gbc.anchor = GridBagConstraints.WEST;
// Right
//gbc.anchor = GridBagConstraints.EAST;
// Top
//gbc.anchor = GridBagConstraints.NORTH;
// Bottom
//gbc.anchor = GridBagConstraints.SOUTH;
// Top/left
//gbc.anchor = GridBagConstraints.NORTHWEST;
// Top/Right
//gbc.anchor = GridBagConstraints.NORTHEAST;
// Bottom/left
//gbc.anchor = GridBagConstraints.SOUTHHWEST;
// Bottom/Right
//gbc.anchor = GridBagConstraints.SOUTHEAST;
// Middle
gbc.anchor = GridBagConstraints.CENTER;
add(pane, gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
It's also the most complex layout manager, so it might take some time and experimentation to get it just right.
Start by having a look at How to Use GridBagLayout
You can use FlowLayout to control the position of the red square.I have set layout to the outer panel with white background to control the position of the inside panel panel_1 which is the red square.Check my answer.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.black);
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel);
JPanel panel_1 = new JPanel();
panel_1.setPreferredSize(new Dimension(200, 200));
panel_1.setBackground(Color.red);
panel.add(panel_1);
//FlowLayout.RIGHT, LEFT, CENTER
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
frame.setSize(800,800);
frame.setVisible(true);
You need to perform some action in order to move the square e.g. I have added a button in my code which when clicked, will cause the square to move. For the button to perform some action, you need to implement ActionListener. As you can see in the actionPerformed method, I am generating random x and y coordinates of the top left corner of the rectangle and setting new coordinates by using the method, setBounds. Note that I have maintained the same width and height of the rectangle when it is moved to new coordinates.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JFrame implements ActionListener {
JPanel panel, panel_1;
JButton btnMoveSquare;
Random random;
MainWindow() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setBackground(Color.black);
getContentPane().setLayout(new GridLayout(1, 1));
panel = new JPanel();
panel.setBackground(Color.WHITE);
getContentPane().add(panel);
panel_1 = new JPanel();
panel_1.setPreferredSize(new Dimension(200, 200));
panel_1.setBackground(Color.red);
panel.add(panel_1);
btnMoveSquare = new JButton("Move Square");
btnMoveSquare.addActionListener(this);
panel.add(btnMoveSquare);
setSize(800, 800);
random = new Random();
}
#Override
public void actionPerformed(ActionEvent e) {
int x = random.nextInt(800);
int y = random.nextInt(800);
panel_1.setBounds(x, y, panel_1.getWidth(), panel_1.getHeight());
}
public static void main(String[] args) {
new MainWindow().setVisible(true);
}
}
Feel free to comment if you have any doubt with the code.

How to set size of a component in a GridLayout and expand JTextArea while typing?

I'm creating a chat but that doesn't matter. I have no issues yet, all is working fine, but I want to change the UI appearance so the user can have a bigger JTextArea instead of a button occupying more space than needed. Also, I would want to resize the JTextArea rather than writing several text in only one line. Finally, I have to thank you for spending your time helping me :D
Objectives:
Set size of JLabel or JTextArea so the button stays smaller.
Expand JLabel when text is reaching the right limit and put it in a new line (kinda WhatsApp).
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTextField;
class MyFirstChatSO extends JFrame {
JLabel title;
JTextArea messages;
JTextField text;
JButton send;
public MyFirstChatSO () {
setLayout(new BorderLayout(0,10));
title = new JLabel("-Chat-");
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(new Font("Gabriola",Font.ITALIC,34));
add(title, BorderLayout.NORTH);
messages = new JTextArea();
messages.setEnabled(false);
messages.setBorder(BorderFactory.createLineBorder(new Color(168,168,168),2,true));
add(messages, BorderLayout.CENTER);
JPanel subPanel = new JPanel();
subPanel.setLayout(new GridLayout(0,2));
text = new JTextField();
subPanel.add(text);
send = new JButton("Send");
subPanel.add(send);
add(subPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
MyFirstChatSO chat = new MyFirstChatSO();
chat.setSize(600,450);
chat.setLocationRelativeTo(null);
chat.setVisible(true);
chat.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
If any other methods such as using different layoutsManagers are the solution it would be good to know about it.
Another fail, but this time with GridBagLayout (I don't know how to use it, help me pls):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTextField;
class MyFirstChatSO extends JFrame {
JLabel title;
JTextArea messages;
JTextField text;
JButton send;
public MyFirstChatSO () {
setLayout(new BorderLayout(0,10));
title = new JLabel("-Chat-");
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(new Font("Gabriola",Font.ITALIC,34));
add(title, BorderLayout.NORTH);
messages = new JTextArea();
messages.setEnabled(false);
messages.setBorder(BorderFactory.createLineBorder(new Color(168,168,168),2,true));
add(messages, BorderLayout.CENTER);
JPanel subPanel = new JPanel();
subPanel.setLayout(new GridBagLayout());
GridBagConstraints gb = new GridBagConstraints();
gb.weightx = 1;
gb.weighty = 1;
gb.fill = GridBagConstraints.HORIZONTAL;
text = new JTextField();
gb.gridx = 0;
gb.gridy = 0;
gb.gridwidth = 6;
gb.fill = GridBagConstraints.HORIZONTAL;
subPanel.add(text,gb);
send = new JButton("Send");
gb.gridx = 7;
gb.gridy = 0;
subPanel.add(send,gb);
add(subPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
MyFirstChatSO chat = new MyFirstChatSO();
chat.setSize(600,450);
chat.setLocationRelativeTo(null);
chat.setVisible(true);
chat.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
Another fail, but this time with GridBagLayout (I don't know how to use it, help me pls):
Yes, you need to understand how it works. Always have How to Use GridBagLayout and the JavaDocs available ;)
So, I started with...
JPanel subPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 4, 4, 4);
text = new JTextArea(1, 80);
text.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY), new EmptyBorder(4, 4, 4, 4)));
subPanel.add(text, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
send = new JButton("Send");
subPanel.add(send, gbc);
And I ended up with something like...
But wait a second, this example is using a JTextArea?! Why!?
Ah, that's because I'm a sneaky, cheaty pants ;)
By using a JTextArea this way, you get an auto expanding text field, for free. Now, it's important to remember, that this is unconstrained, meaning that the user could keeping pressing enter and making the JTextArea fill up more and more space.
To fix that becomes complicated and I'd look into the Scrollable interface for some ideas

Java GUI layout cannot quite get it right

I tried a bunch of different layouts but none are giving me the desired effect.
I want something like this:
+-----------------------------+
Centered Text
+-------+
|Button |
+-------+
+-----------------------------+
In html it might look like this:
<p align="center">Some text</p>
<input type="button" value="Press"/>
The trouble I am having is with certain layouts (BorderLayout) it likes to resize the button to fit. Other layouts (Boxlayout and GroupLayout) will do something like this:
+-----------------------------+
Centered Text
+-------+
|Button |
+-------+
+-----------------------------+
Even when I have the JLabel aligned to CENTER and the Button aligned to LEFT.
Much appreciation to my helpers.
There are a number layouts that would be able to achieve this, in fact, you might even be able to use BorderLayout and FlowLayout together to do this, but this example simply uses GridBagLayout
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ExampleLayout {
public static void main(String[] args) {
new ExampleLayout();
}
public ExampleLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
JLabel center = new JLabel("Centered Text");
center.setHorizontalAlignment(JLabel.CENTER);
add(center, gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.weightx = 0;
gbc.anchor = GridBagConstraints.WEST;
JButton button = new JButton("Button");
add(button, gbc);
}
}
}
Take a look at Laying Out Components Within a Container for more examples and details
Although MadProgrammer and Costis Aivalis already answered your question, here is also an answer with MigLayout:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel label = new JLabel("Centered text");
JButton button = new JButton("Button");
public MigLayoutDemo() {
panel.setLayout(new MigLayout());
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label, "wrap, pushx, growx");
panel.add(button);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(MigLayoutDemo::new);
}
}
Same effect, but this approach is less verbose unlike in case of GridBagLayout and I personally think that MigLayout is easier to use.
FlowLayout(int align) allows you to define justification. The default is CENTER. If you just left justify the FlowLayout of the panel that contains your button it works without having to use GridBagLayout manually. NetBeans provide an excellent GridBagLayout customizer, but you do not want to touch the code it generates automatically.
import javax.swing.*;
import java.awt.*;
public class MyLooks extends JFrame {
public MyLooks() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
p = new JPanel(new GridLayout(2, 1));
p1 = new JPanel();
p2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
myLabel = new JLabel("this is a label");
myButton = new JButton("press");
p1.add(myLabel);
p2.add(myButton);
p.add(p1);
p.add(p2);
setContentPane(p);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MyLooks().setVisible(true);
}
});
}
private JLabel myLabel;
private JButton myButton;
private JPanel p, p1, p2;
}

How do I get my JButton to both switch the JPanel and close the JFrame?

I've managed to get the JButton buttonOne in class Database to switch panels, but at the same time it's opening a new JFrame to do this. How can I change it so it just changes the JFrame panel without having to open another JFrame? I have a feeling I could do this if I could return both JPanel and JFrame but I don't know how to do so. Thanks for any help :
First class, with the JFrame and the JPanel that is being switched to on click of 'buttonOne' :
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDatabaseFarme;
import javax.swing.JLabel;
public class Database{
//Running the GUI
public static void main(String[] args) throws IOException {
Database gui2 = new Database();
gui2.mainPanel();
}
JDatabaseFarme mainPanel() throws IOException {
// GridBagLayout/Constraint
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(15,15,15,15);
final JDatabaseFarme DatabaseFarme = new JDatabaseFarme("Lohn Jocke and the Quest for Qualia"); //Had to set DatabaseFarme to final for the action listener
//JPanel panel = new JPanel(new GridBagLayout()); (??)
final JComponent panel = new JLabel(new ImageIcon(ImageIO.read(new File("res/FinalBG.png")))); //Had to set panel to final for the action listener
panel.setLayout(new GridBagLayout());
////// Creating JButtons/Icons for the buttons ////
BufferedImage buttonIcon = ImageIO.read(new File("res/PlayGame.png"));
JButton button = new JButton ("", new ImageIcon(buttonIcon));
BufferedImage buttonIcon2 = ImageIO.read(new File("res/Scoreboard.png"));
JButton buttonTwo = new JButton ("", new ImageIcon(buttonIcon2));
BufferedImage buttonIcon3 = ImageIO.read(new File("res/SQLs.png"));
JButton buttonThree = new JButton ("",new ImageIcon(buttonIcon3));
// Scoreboard button ActionListener
buttonThree.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
//removed some code from here
try {
panel.setVisible(false);
SQLsPanel a = new SQLsPanel();
JComponent SQLsPanel = a.SQLsPanel();
DatabaseFarme.add(SQLsPanel);
DatabaseFarme.getContentPane().add(BorderLayout.CENTER, SQLsPanel);
SQLsPanel.setVisible(true);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
////// Creating/adding button rollover images /////
BufferedImage buttonIcon1b = ImageIO.read(new File("res/PlayGameHigh.png"));
button.setRolloverIcon(new ImageIcon(buttonIcon1b));
BufferedImage buttonIcon2b = ImageIO.read(new File("res/ScoreboardHigh.png"));
buttonTwo.setRolloverIcon(new ImageIcon(buttonIcon2b));
BufferedImage buttonIcon3b = ImageIO.read(new File("res/SQLsHigh.png"));
buttonThree.setRolloverIcon(new ImageIcon(buttonIcon3b));
// Setting up GridBagConstraints for each JButton
gbc.weightx=1;
gbc.weighty=0;
gbc.gridx=0;
gbc.gridy=0;
gbc.anchor = GridBagConstraints.CENTER;
panel.add(button, gbc); //PLAY GAME
gbc.weightx=1;
gbc.weighty=0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx=0;
gbc.gridy=1;
panel.add(buttonTwo,gbc); //SCOREBOARD
gbc.weightx=1;
gbc.weighty=0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx=0;
gbc.gridy=2;
panel.add(buttonThree,gbc); //SQLS
// JDatabaseFarme settings
DatabaseFarme.add(panel);
DatabaseFarme.getContentPane().add(BorderLayout.CENTER, panel);
DatabaseFarme.setSize(860,500);
DatabaseFarme.setLocationRelativeTo(null);
DatabaseFarme.setDefaultCloseOperation(JDatabaseFarme.EXIT_ON_CLOSE);
DatabaseFarme.setResizable(false);
DatabaseFarme.setVisible(true);
// JButton icon details
button.setBorder(BorderFactory.createEmptyBorder());
button.setContentAreaFilled(false);
buttonTwo.setBorder(BorderFactory.createEmptyBorder());
buttonTwo.setContentAreaFilled(false);
buttonThree.setBorder(BorderFactory.createEmptyBorder());
buttonThree.setContentAreaFilled(false);
return DatabaseFarme;
}
}
My second class, it contains the JButton that needs to change panel and close the JDatabaseFarme :
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDatabaseFarme;
import javax.swing.JLabel;
public class SQLsPanel {
JComponent SQLsPanel() throws IOException {
final JComponent SQLsPanel = new JLabel(new ImageIcon(ImageIO.read(new File("res/HowToPlayBG.png"))));
SQLsPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
BufferedImage buttonOneIcon = ImageIO.read(new File("res/Database.png"));
JButton buttonOne = new JButton("",new ImageIcon(buttonOneIcon));
BufferedImage buttonOneIconB = ImageIO.read(new File("res/DatabaseHigh.png"));
buttonOne.setRolloverIcon(new ImageIcon(buttonOneIconB));
buttonOne.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
SQLsPanel.setVisible(false);
try {
Database passme = new Database();
JDatabaseFarme DatabaseFarmeA = passme.mainPanel();
DatabaseFarmeA.add(SQLsPanel);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
gbc = new GridBagConstraints();
gbc.insets = new Insets(15,15,15,15);
gbc.weighty = 1;
gbc.weightx = 1;
gbc.gridx = 1;
gbc.gridy = 3;
gbc.anchor = GridBagConstraints.PAGE_END;
SQLsPanel.add(buttonOne, gbc);
buttonOne.setBorder(BorderFactory.createEmptyBorder());
buttonOne.setContentAreaFilled(false);
return SQLsPanel;
}
}
Try the following:
final JFrame frame = new JFrame("Lohn Jocke and the Quest for Qualia"); //Had to set frame to final for the action listener
final String name = frame.getName();
Add the variable 'name' just below where you declare the JFrame.
// JFrame settings
frame.add(panel);
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.setSize(860,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
if(Frame.getFrames().length > 1){
Frame[] f = Frame.getFrames();
for(Frame frames : f){
if(!frames.getName().equals(name)){
frames.dispose();
}
}
}
Add this below where you set the JFrame settings.
what happens is when you call this
MainMenu passme = new MainMenu();
From the InstructionsPanel you are creating a new JFrame from your class constructor in addition to the current frame you already have(Hence why you end up with 2). what I have tried to do is get the name of your new Frame you are creating(with the name variable), then using the loop at the bottom wipe all other Frames away leaving you with the new one with which to display your Panel.(Frame.getFrames() returns a list of all frames, I then iterate over removing all the ones that aren't needed)
You may want to tweak it if you add more JFrames in future but hopefully this will be somewhat effective for you for now at least.(i have tried to replicate your code with dummy images to grasp at the problem for this 'fix' so apologies if I have misunderstood the issue here )
Hope this helps.

Categories