Java Swing Glue not working between 2 buttons - java

I am trying to make my own little game in Java as a personal excercise however I am finding a lot of issues using BoxLayout's in Java Swing.
So I have a basic MVC application and I need two buttons at the top both "New Game" and "Submit" to both be on the same line in the GUI. I have found out that I can use glue to do this however all of the guides I have found on it, do not work. Am I missing something obvious here?
This is my view code (my GUI):
package mvc;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.Map;
import java.util.Set;
import javax.swing.*;
public class View extends JFrame {
//User input Characters
private JTextField firstChar = new JTextField(1);
private JTextField secondChar = new JTextField(1);
private JTextField thirdChar = new JTextField(1);
private JTextField fourthChar = new JTextField(1);
private JTextField fifthChar = new JTextField(1);
//Displays on GUI
private JButton submitButton = new JButton("Submit");
private JButton newButton = new JButton("New Game");
View() {
JPanel gamePanel = new JPanel();
gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 200);
gamePanel.add(submitButton);
gamePanel.add(Box.createHorizontalGlue());
gamePanel.add(newButton);
gamePanel.add(firstChar);
gamePanel.add(secondChar);
gamePanel.add(thirdChar);
gamePanel.add(fourthChar);
gamePanel.add(fifthChar);
this.add(gamePanel);
}
}
Any help would be massively appreciated!
I have tried using glue and rigid area's to solve this however neither worked. I am expecting both buttons to be on the same line in my GUI

You use Boxlayout, that according to https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/javax/swing/BoxLayout.html
A layout manager that allows multiple components to be laid out either vertically or horizontally.
In your case it is vertical, and I never used Glue so I am not even aware whether it can change that behaviour.
But you can for sure put the two buttons in an extra panel and add that to your gamePanel, like so:
JPanel buttonBar = new JPanel();
buttonBar.setLayout(new FlowLayout());
buttonBar.add(submitButton);
buttonBar.add(newButton);
gamePanel.add(buttonBar);

BoxLayout can either lay out the components along the X_AXIS or along the Y_AXIS. You cannot mix this two layout directions with a single BoxLayout.
One way to solve your problem is to wrap both buttons in a JPanel and use a BoxLayout(.., BoxLayout.X_AXIS) to lay out this button panel.
You would then add the button panel as the first element of the gamePanel:
package mvc;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.Map;
import java.util.Set;
import javax.swing.*;
public class View extends JFrame {
//User input Characters
private JTextField firstChar = new JTextField(1);
private JTextField secondChar = new JTextField(1);
private JTextField thirdChar = new JTextField(1);
private JTextField fourthChar = new JTextField(1);
private JTextField fifthChar = new JTextField(1);
//Displays on GUI
private JButton submitButton = new JButton("Submit");
private JButton newButton = new JButton("New Game");
View() {
JPanel gamePanel = new JPanel();
gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 200);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
buttonPanel.add(submitButton);
buttonPanel.add(Box.createHorizontalGlue());
buttonPanel.add(newButton);
gamePanel.add(buttonPanel);
gamePanel.add(firstChar);
gamePanel.add(secondChar);
gamePanel.add(thirdChar);
gamePanel.add(fourthChar);
gamePanel.add(fifthChar);
this.add(gamePanel);
}
}

Related

How to fix the position of the JPanels after expanding the JFrame

I am trying to make the interface of a program using Java Swing. I have a container where I add 3 JPanels with some components. The problem is that when I expand the frame all those 3 JPanels come on the first row one next to another.
Here is my code:
import java.awt.Color;
import java.awt.Container;
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.SpringLayout;
import javax.swing.border.LineBorder;
public class GraphicRefact extends JFrame {
private Container container;
private JButton button2;
private JButton button1;
private JTextField textField01;
private JLabel label01;
private JButton button03;
private JButton button04;
private JTextField textField03;
private JLabel label03;
private JButton button02;
private JButton button01;
private JTextField textField02;
private JLabel label02;
public static void main(String[] args) {
new GraphicRefact();
}
public GraphicRefact() {
initializeComponents();
setTitle("Title");
setSize(500, 150);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
container = new JPanel();
JPanel panel01 = new JPanel();
panel01.add(label01);
panel01.add(textField01);
panel01.add(button2);
panel01.add(button1);
panel01.setBorder(new LineBorder(Color.BLACK, 3));
container.add(panel01);
JPanel panel02 = new JPanel();
panel02.add(label02);
panel02.add(textField02);
panel02.add(button02);
panel02.add(button01);
container.add(panel02);
JPanel panel03 = new JPanel();
panel03.add(label03);
panel03.add(textField03);
panel03.add(button03);
panel03.add(button04);
container.add(panel03);
add(container);
}
private void initializeComponents() {
button1 = new JButton("Open");
button2 = new JButton("Close");
textField01 = new JTextField("Choose the path...");
label01 = new JLabel("Choose File: ");
button01 = new JButton("Button01");
button02 = new JButton("Button02");
textField02 = new JTextField("Choose the path...");
label02 = new JLabel("Choose Dir:");
button03 = new JButton("Button03");
button04 = new JButton("Button03");
textField03 = new JTextField("Choose the path...");
label03 = new JLabel("Choose Dir:");
}
}
Here is how the program looks before and after I expand the frame.
Before:
After:
So, even after I expand the frame, I want the program to leave those 3 JPanels on the middle of cotainer.
Thank you!
You can set the gridLayout and put those elements inside.
JPanel jp = new JPanel();
GridLayout gl = new GridLayout(3,4); //3 rows, 4 columns
jp.setLayout(gl);
After you do this, just put your elements inside layout, by order.
jp.add(label1);
jp.add(button1);
//etc...
You have to use a proper LayoutManager. Look at the examples there. BoxLayout seems to be what you want.
I can't see where you have defined any positions for anything, if you need to read how that's done you can start here
Positioning a JPanel in a JFrame at specific position
The inbuilt layout manger of java swing are not that useful.
You should use this
frame.setLayout(null);
component.setLocation(x, y);
frame.add(component);

GUI Calculator using JFrames and layouts

I'm currently working on a calculator which should perform basic calculations such as addition, subtraction, multiplication, and division. To achieve the final outcome, I've to follow a certain design for the calculator. The design of the calculator is provided with this question. I've given my best on how to match the official design of the calculator but it's not matching it.
This is the OFFICIAL design of the calculator. This is how it should look.
This is WHAT I'm getting when I run the code.
The CODE:
package patel.Jainam;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class CalculatorFrame extends JFrame {
/**
* All the buttons that will be used in the calculator have been initialized
*/
private JButton button1;
private JButton button2;
private JButton button3;
private JButton button4;
private JButton button5;
private JButton button6;
private JButton button7;
private JButton button8;
private JButton button9;
private JButton button0;
private JButton buttonEqual;
private JButton buttonDot;
private JButton buttonClearLast;
private JButton buttonClearAll;
private JButton buttonAdd;
private JButton buttonSub;
private JButton buttonMul;
private JButton buttonDiv;
private JTextArea textArea;
public CalculatorFrame(){
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(1,1));
panel2.add(buttonClearLast = new JButton ("Clear Last"));
panel2.add(buttonClearAll = new JButton ("Clear All"));
add(panel2, BorderLayout.PAGE_START);
JPanel panel3 = new JPanel();
textArea = new JTextArea(2,10);
// textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
panel3.add(scrollPane);
add(panel3, BorderLayout.LINE_START);
JPanel panel1 = new JPanel();
panel1.setLayout(new GridLayout(4,4));
panel1.add(button7 = new JButton ("7"));
panel1.add(button8 = new JButton ("8"));
panel1.add(button9 = new JButton ("9"));
panel1.add(buttonAdd = new JButton ("+"));
panel1.add(button4 = new JButton ("4"));
panel1.add(button5 = new JButton ("5"));
panel1.add(button6 = new JButton ("6"));
panel1.add(buttonSub = new JButton ("-"));
panel1.add(button1 = new JButton ("1"));
panel1.add(button2 = new JButton ("2"));
panel1.add(button3 = new JButton ("3"));
panel1.add(buttonMul = new JButton ("*"));
panel1.add(button0 = new JButton ("0"));
panel1.add(buttonDot = new JButton ("."));
panel1.add(buttonEqual = new JButton ("="));
panel1.add(buttonDiv = new JButton ("/"));
add(panel1, BorderLayout.PAGE_END);
}
}
Thank you.
The problem is you are over using the GridLayout.
I would suggest you want to keep using the default layout manager of the frame which is a BorderLayout.
Then you would do the following:
Create a panel using a GridLayout for the two buttons. Add this panel to the BorderLayout.PAGE_START of the frame.
Add your scroll pane containing the text area to the BorderLayout.CENTER of the frame.
Create a panel using the GridLayout for the buttons on the bottom. Add this panel to the BorderLayout.PAGE_END of the frame.
Read the section from the Swing tutorial on Using Layout Managers for more information and working examples of the Borderlayout and GridLayout.
camickr's answer is optimal here.
Here is an SSCCE:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class CalculatorFrame extends JFrame {
public CalculatorFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(createClearPanel(), BorderLayout.PAGE_START);
getContentPane().add(createTextArea(), BorderLayout.CENTER);
getContentPane().add(createNumberPanels(), BorderLayout.PAGE_END);
setSize(300, 300);
pack();
}
private JPanel createNumberPanels() {
JPanel main = new JPanel();
main.setLayout(new GridLayout(4, 0));
for (int i = 0; i < 16; i++) {
JButton button = new JButton("" + i);
main.add(button);
}
return main;
}
private JScrollPane createTextArea() {
JTextArea area = new JTextArea(5, 10);
JScrollPane sp = new JScrollPane(area);
sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
return sp;
}
private JPanel createClearPanel() {
JButton clearAll = new JButton("clear all");
JButton clearLast = new JButton("Clear last");
JPanel panel = new JPanel(new GridLayout(1, 0));
panel.add(clearLast);
panel.add(clearAll);
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new CalculatorFrame().setVisible(true));
}
}
Preview:
P.S: Ignore the fact i used only numbers instead of operators like *,?,+,= etc.

BorderLayout(); buttons not showing up

Hey guys my buttons and textarea will not display on JFrame when compiled, i have tried everything and searched this site but no luck. Any help would be greatly appreciated. Due to them not letting me post without more detail i am just adding this part so i can hit the submit button.
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class DataManager extends JFrame {
private String students[] = {"John Smith","Ken Hanson","Michael Li","John Andersen","Fiona Harris","Angela Lim","Bob London","Sydney Shield","Tina Gillard",
"Ross Brinns","Scott Cairns","Grant Peterson","David Power","Joshua Kane","Alan Newton","Frady Morgan","Quinn Perth"};
private int english[] = {80,52,71,61,39,62,31,46,60,26,77,40,58,38,94,90,97};
private int maths[] = {60,45,77,90,45,55,66,87,31,42,65,55,80,71,51,55,95};
private int total[];
private JButton sortNameButton;
private JButton sortTotalButton;
private JTextField searchTextField;
private JButton statisticsButton;
private JButton exitButton;
private JTextArea infoTextArea;
private JPanel jPan;
public DataManager() {
super("Data Manager ");
jPan = new JPanel();
sortNameButton = new JButton("Sort By Name");
sortTotalButton = new JButton("Sort By Total");
searchTextField = new JTextField("Search");
statisticsButton = new JButton("Statistics");
exitButton = new JButton("Exit");
infoTextArea = new JTextArea();
setLayout(new BorderLayout());
jPan.add(sortNameButton, BorderLayout.NORTH);
jPan.add(sortTotalButton, BorderLayout.NORTH);
jPan.add(searchTextField, BorderLayout.NORTH);
jPan.add(statisticsButton, BorderLayout.NORTH);
jPan.add(exitButton, BorderLayout.NORTH);
jPan.add(infoTextArea, BorderLayout.CENTER);
}
public static void main(String[] args) {
DataManager frame = new DataManager();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,600);
frame.setVisible(true);
} // End of main method.
} // End of DataManager class
You add your JButtons to the jPan JPanel but never add the jPan to anything -- it must be added to your JFrame, to this to be seen.
jPan.add(sortNameButton);
jPan.add(sortTotalButton);
jPan.add(searchTextField);
jPan.add(statisticsButton);
jPan.add(exitButton);
jPan.add(infoTextArea);
add(jPan); // don't forget this! ************
Note other problems:
You set the JFrame's layout to BorderLayout -- it's already using BorderLayout
You add components to your jPan JPanel with BorderLayout constants, but it's not using a BorderLayout.
If it were, many buttons would not be seen since many are added to the same BorderLayout position and will cover the previous component added there.
In other words, read the tutorials as you're making wrong assumptions.
Better would be something like:
// setLayout(new BorderLayout());
jPan.setLayout(new BorderLayout());
JPanel northPanel = new JPanel(); // **** to hold buttons
northPanel.add(sortNameButton);
northPanel.add(sortTotalButton);
northPanel.add(searchTextField);
northPanel.add(statisticsButton);
northPanel.add(exitButton);
jPan.add(northPanel, BorderLayout.PAGE_START);
jPan.add(infoTextArea, BorderLayout.CENTER);

Coding a GUI in Java however my labels never seem to appear

I am creating a GUI using BlueJ - Java, i have made the entry boxes however i cant seem to add a label to go either above each one or to the left. Could anyone help me out and tell me where im going wrong ? My code is below:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Log extends JFrame {
public static void main(String[] args){
Log frameTabel = new Log();
}
JButton Confirm = new JButton("Confirm");
JPanel panel = new JPanel();
JLabel label1 = new JLabel("Name", JLabel.RIGHT);
JTextField FullName = new JTextField(15);
JTextField Address1line = new JTextField(15);
JTextField postcode = new JTextField(15);
JTextField Destination = new JTextField(15);
JTextField Date = new JTextField(15);
JTextField MilesTravelling = new JTextField(15);
JLabel lblMsg = new JLabel ("Name",JLabel.LEFT);
Log(){
super("Customer GUI");
setSize(300,400);
setLocation(400,250);
panel.setLayout(null);
FullName.setBounds(70,30,150,20);
Address1line.setBounds(70,80,150,20);
postcode.setBounds(70,130,150,20);
Destination.setBounds(70,180,150,20);
Date.setBounds(70,230,150,20);
MilesTravelling.setBounds(70,280,150,20);
Confirm.setBounds(105,320,80,20);
panel.add(lblMsg);
panel.add(Confirm);
panel.add(FullName);
panel.add(Address1line);
panel.add(postcode);
panel.add(Destination);
panel.add(Date);
panel.add(MilesTravelling);
getContentPane().add(label1);
getContentPane().add(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
JFrames ContentPane uses BorderLayout, BorderLayout has 5th areas and only one JComponent can be placed in the one of areas
.
getContentPane().add(label1); //JFrames CENTER area
getContentPane().add(panel);
then last added JComponent can be visible
.
getContentPane().add(panel);
suggestions don't to use NullLayout and Log frameTabel = new Log(); should be wrapped into invokeLater (Swing GUI should be created and intialized on EventDispatchThread), more to see in Oracle tutorial Initial Thread

GUI not showing as intended

I'm trying to draw a gui like shown in the figure, but somehow I'm not able to place the objects in right place (I guess that the problem is with the layout) the textArea is suppose to go in the middle... but is not showing at all
package Chapter22Collections;
import javax.swing.*;
import java.awt.*;
public class Exercise226 extends JFrame {
private JButton jbSort;
private JButton jbReverse;
private JButton jbAdd;
private JButton jbShuffle;
private JLabel jlAddnum;
private JTextArea jTextDisplay;
private JTextField jTextAdd;
public Exercise226() {
jbSort = new JButton("Sort");
jbReverse = new JButton("Reverse");
jbShuffle = new JButton("Shuffle");
jbAdd = new JButton("Add");
jlAddnum = new JLabel("Add number here: ");
jTextDisplay = new JTextArea();
jTextAdd = new JTextField(8);
setLayout(new BorderLayout());
JPanel p1 = new JPanel(new GridLayout(1,3));
p1.add(jlAddnum);
p1.add(jTextAdd);
p1.add(jbAdd);
JPanel p2 = new JPanel(new GridLayout(1,3));
p2.add(jbSort);
p2.add(jbReverse);
p2.add(jbShuffle);
add(p1, BorderLayout.NORTH);
add(jTextDisplay, BorderLayout.CENTER);
add(p2, BorderLayout.SOUTH);
}
public static void main(String... args) {
Exercise226 gui = new Exercise226();
gui.setTitle("Numbers");
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(300, 200);
gui.setLocationRelativeTo(null);
gui.setVisible(true);
}
}
The JTextArea is actually where you expect it to be but has no outline border. It is usual to place the component in a JScrollPane which will give this effect:
add(new JScrollPane(jTextDisplay), BorderLayout.CENTER);
or simply
add(new JScrollPane(jTextDisplay));
To make the textArea re-size with the window, try BoxLayout. Box is "A lightweight container that uses a BoxLayout object as its layout manager."
Box p1 = new Box(BoxLayout.X_AXIS);
How could I add spacing/padding between the elements in the frame? So the text area is more visible and centered.
Borders and padding. E.G.
Compared with:
import javax.swing.*;
import java.awt.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
public class Exercise226 {
private JButton jbSort;
private JButton jbReverse;
private JButton jbAdd;
private JButton jbShuffle;
private JLabel jlAddnum;
private JTextArea jTextDisplay;
private JTextField jTextAdd;
private JPanel gui;
public Exercise226() {
gui = new JPanel(new BorderLayout(5,5));
jbSort = new JButton("Sort");
jbReverse = new JButton("Reverse");
jbShuffle = new JButton("Shuffle");
jbAdd = new JButton("Add");
jlAddnum = new JLabel("Add number here: ");
// set the size constraints using columns/rows
jTextDisplay = new JTextArea("Here I am!", 6,20);
jTextAdd = new JTextField(8);
JPanel p1 = new JPanel(new GridLayout(1,3,3,3));
p1.add(jlAddnum);
p1.add(jTextAdd);
p1.add(jbAdd);
JPanel p2 = new JPanel(new GridLayout(1,3,3,3));
p2.add(jbSort);
p2.add(jbReverse);
p2.add(jbShuffle);
JPanel textAreaContainer = new JPanel(new GridLayout());
textAreaContainer.add(new JScrollPane(jTextDisplay));
textAreaContainer.setBorder(new TitledBorder("Text Area Here"));
gui.add(p1, BorderLayout.PAGE_START);
gui.add(textAreaContainer, BorderLayout.CENTER);
gui.add(p2, BorderLayout.PAGE_END);
gui.setBorder(new EmptyBorder(4,4,4,4));
}
public Container getGui() {
return gui;
}
public static void main(String... args) {
JFrame f = new JFrame();
Exercise226 gui = new Exercise226();
f.setContentPane(gui.getGui());
f.setTitle("Numbers");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
}
This code:
Primarily provides 'white space' in the GUI using different constructors for the layouts that accept 2 int arguments for horizontal & vertical spacing.
Also adds 2 borders:
An empty border around the entire GUI to provide some spacing between it and the frame decorations.
A titled border around the text area, to make it very obvious.
Does implement a change for one unnecessary part of the original code. Instead of extending frame, it simply retains an instance of one.
Uses the JScrollPane container for the text area, as suggested by #Reimeus. It adds a nice beveled border of its own to an element that needs no scroll bars.
Creates a textAreaContainer specifically so that we can set a titled border to surround the scroll pane - without interfering with its existing border. It is possible to use a CompoundBorder for the scroll pane that consists of the existing border (scroll.getBorder()) & the titled border. However that gets complicated with buttons & other elements that might change borders on selection or action. So to set an 'outermost border' for a screen element (like the text area here) - I generally prefer to wrap the entire component in another container first.
Does not create and show the GUI on the EDT. Swing GUIs should be created and modified on the EDT. Left as an exercise for the user. See Concurrency in Swing for more details.
Old Code
The original code on this answer that provides the 'comparison GUI image' seen above. IT is closely based on the original code but with the text area wrapped in a scroll pane (and gaining a beveled border because of that) & given some text to display.
import javax.swing.*;
import java.awt.*;
public class Exercise226 extends JFrame {
private JButton jbSort;
private JButton jbReverse;
private JButton jbAdd;
private JButton jbShuffle;
private JLabel jlAddnum;
private JTextArea jTextDisplay;
private JTextField jTextAdd;
public Exercise226() {
jbSort = new JButton("Sort");
jbReverse = new JButton("Reverse");
jbShuffle = new JButton("Shuffle");
jbAdd = new JButton("Add");
jlAddnum = new JLabel("Add number here: ");
// set the size constraints using columns/rows
jTextDisplay = new JTextArea("Here I am!", 6,20);
jTextAdd = new JTextField(8);
setLayout(new BorderLayout());
JPanel p1 = new JPanel(new GridLayout(1,3));
p1.add(jlAddnum);
p1.add(jTextAdd);
p1.add(jbAdd);
JPanel p2 = new JPanel(new GridLayout(1,3));
p2.add(jbSort);
p2.add(jbReverse);
p2.add(jbShuffle);
add(p1, BorderLayout.NORTH);
add(new JScrollPane(jTextDisplay), BorderLayout.CENTER);
add(p2, BorderLayout.SOUTH);
}
public static void main(String... args) {
Exercise226 gui = new Exercise226();
gui.setTitle("Numbers");
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//gui.setSize(300, 200);
gui.pack();
//gui.setLocationRelativeTo(null);
gui.setLocationByPlatform(true);
gui.setVisible(true);
}
}

Categories