I currently have a jpanel with layout set to GridBagLayout, with gbc = new GridBagConstraints();, However for whatever value of x, y or gridwidth,gridheight the items don't move at all.
I would greatly appreciate an expert eye to look over my code to see what I am missing, Thanks in advance.
Edit: Added the imports and the main method
Edit 2: turns out I was thinking the x and y values were pixels and that was the reason it wasn't working
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class HomeScreenUI {
public void addobjects(Component componente, Container yourcontainer, GridBagLayout layout, GridBagConstraints gbc, int gridx, int gridy, int gridwidth, int gridheight){
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
layout.setConstraints(componente, gbc);
yourcontainer.add(componente);
}
HomeScreenUI(){
//frame
JFrame frame = new JFrame("Opisa");
//panels, one before button click and one after
JPanel panel = new JPanel();
JPanel panelAfterButtonClick = new JPanel();
GridBagLayout ourlayout;
ourlayout = new GridBagLayout();
panel.setLayout(ourlayout);
panelAfterButtonClick.setLayout(ourlayout);
GridBagConstraints gbc = new GridBagConstraints();
//jlabel that isnt displaying + dimensions
JLabel label = new JLabel("Opisa");
label.setFont(new Font("Helvetica", Font.PLAIN, 70));
//second jlabel that isn't displaying
JLabel label2 = new JLabel("Home");
label2.setFont(new Font("Helvetica", Font.PLAIN, 70));
//adding the labels to the panels
panel.add(label);
panelAfterButtonClick.add(label2);
//button that is displaying both before and after
JButton button = new JButton("Click Me..");
JButton buttonAfterClick = new JButton("Clicked Me..");
//adding the buttons to the jpanel
this.addobjects(label, panel, ourlayout, gbc, 0,0, 3, 1);
this.addobjects(button, panel, ourlayout, gbc, 700, 100, 2, 0);
this.addobjects(label2, panelAfterButtonClick, ourlayout, gbc, 200, 200, 1, 1);
this.addobjects(buttonAfterClick, panelAfterButtonClick, ourlayout, gbc, 700, 10, 2, 0);
//function that changes the panel after the button is clicked
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
frame.setContentPane(panelAfterButtonClick);
frame.invalidate();
frame.validate();
}
});
//adding the panel to the frame and setting the size
frame.add(panel);
frame.setSize(720,1280);
frame.setVisible(true);
}
}
public static void main (String args[]) {
HomeScreenUI hs = new HomeScreenUI();
}
It seems you are using GridBagLayout completely different than it was designed for.
Note you have one instance of GridBagLayout but want to use it for two panels. Each panel needs to have it's own LayoutManager instance.
Then look how many GridBagConstraints you have. Each Component that shall be added needs it's own instance to be properly managed.
Then there are strange values you are passing into GridBagConstraints. I suggest you take the time and go through How to Use GridBagLayout.
I modified your code to create the following GUI.
Here's what it looks like after you left-click the button.
You can swap back and forth between the two panels.
Here are the major changes I made to your code.
Code should be organized like an essay. The most important code should come first, followed by the less important code.
Break your code up into methods and classes. Each method should do one thing and do it well. This is called separation of concerns and it helps you to focus on one part of your code at a time.
To start the Swing application, I made a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
The JFrame code is in the class constructor. The JFrame code has to be called in a certain order. This is the order I use for most of my Swing applications. Don't forget to call the setDefaultCloseOperation method. The JFrame.EXIT_ON_CLOSE parameter exits the application when you close the JFrame.
I used a CardLayout to hold the two subordinate JPanels. I created the CardLayout in its own method.
I created each subordinate JPanel in its own method. I used a GridBagLayout for both subordinate JPanels. As you can see in the code, you have to set quite a few GridBagConstraints parameters.
I created an anonymous ActionListener for each of the JButtons. The ActionListeners swap the two subordinate JPanels in the CardLayout.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class HomeScreenUI {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new HomeScreenUI();
}
});
}
private CardLayout cardLayout;
private JPanel cardPanel;
public HomeScreenUI() {
JFrame frame = new JFrame("Opisa");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.cardPanel = createCardPanel();
frame.add(cardPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createCardPanel() {
cardLayout = new CardLayout();
JPanel panel = new JPanel(cardLayout);
panel.add(createOpisaPanel(), "Opisa");
panel.add(createHomePanel(), "Home");
return panel;
}
private JPanel createOpisaPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
// jlabel that isnt displaying + dimensions
JLabel label = new JLabel("Opisa");
label.setFont(new Font("Helvetica", Font.PLAIN, 72));
panel.add(label, gbc);
gbc.gridy++;
JButton button = new JButton("Click Me..");
// function that changes the panel after the button is clicked
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
cardLayout.show(cardPanel, "Home");
}
});
panel.add(button, gbc);
return panel;
}
private JPanel createHomePanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
// second jlabel that isn't displaying
JLabel label2 = new JLabel("Home");
label2.setFont(new Font("Helvetica", Font.PLAIN, 72));
panel.add(label2, gbc);
gbc.gridy++;
JButton buttonAfterClick = new JButton("Clicked Me..");
buttonAfterClick.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
cardLayout.show(cardPanel, "Opisa");
}
});
panel.add(buttonAfterClick, gbc);
return panel;
}
}
Related
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI_Borrower extends JFrame implements ActionListener {
JPanel panel = new JPanel();
JLabel lblName = new JLabel("Name:");
JLabel lblProg = new JLabel("Program:");
JLabel lblId = new JLabel("Library ID: ");
JLabel lblTitle = new JLabel("Add Borrower");
JTextField txtName = new JTextField(10);
JTextField txtProg = new JTextField(10);
JTextField txtId = new JTextField(10);
static int counter = 19000;
JButton btnSubmit = new JButton("Submit");
public GUI_Borrower() {
super("Add Borrower");
makeFrame();
showFrame();
}
public void makeFrame() {
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
add(lblTitle);
add(lblName);
add(txtName);
add(lblProg);
add(txtProg);
add(lblId);
add(txtId);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(btnSubmit);
btnSubmit.addActionListener(this);
}
public void showFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtProg.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") && txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
counter++;
txtId.setText("" + counter);
btnSubmit.setText("Confirm");
}
}
}
public static void main(String[] args) {
new GUI_Borrower();
}
}
I tried adding BoxLayout because all the text fields and labels are on one line. So I tried box Layout and failed.
Can anyone show me how to make it like the title one line, label Different line, button different line?
Like this:
As camickr says in his comment, you generally use a GridBagLayout to create a form.
I reworked your code because I hope to show a better way to code a GUI panel.
Here's the GUI.
The major changes I made include:
All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
I organized the GUI code into three methods so I could focus on one part of the GUI at a time. The JFrame is created in the run method. The title JPanel is created in the createTitlePanel method. The form JPanel is created in the createFormPanel method. The code for the JFrame will rarely change from Swing application to Swing application.
I use Swing components. I don't extend Swing components, or any Java class, unless I intend to override one of the class methods.
The createFormPanel class uses the GridBagLayout to organize the labels and text fields in columns. You can think of the GridBagLayout as a flexible grid. The cells of the grid don't have to be the same size. The Oracle tutorial, How to Use GridBagLayout, has another example.
I put the ActionListener in a separate class. I made it an inner class in this example so I could paste the code as one file. Generally, you should put separate classes in separate files. It makes each class shorter and easier to understand.
Here's the runnable, example code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
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 BorrowerGUI implements Runnable {
private static int ID_COUNTER = 19000;
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorrowerGUI());
}
private JButton btnSubmit;
private JTextField txtName;
private JTextField txtProg;
private JTextField txtId;
#Override
public void run() {
JFrame frame = new JFrame("Add Borrower");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTitlePanel(), BorderLayout.BEFORE_FIRST_LINE);
frame.add(createFormPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTitlePanel() {
JPanel panel = new JPanel(new FlowLayout());
JLabel lblTitle = new JLabel("Add Borrower");
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle);
return panel;
}
private JPanel createFormPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblName = new JLabel("Name:");
panel.add(lblName, gbc);
gbc.gridx++;
txtName = new JTextField(20);
panel.add(txtName, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblProg = new JLabel("Program:");
panel.add(lblProg, gbc);
gbc.gridx++;
txtProg = new JTextField(20);
panel.add(txtProg, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblId = new JLabel("Library ID:");
panel.add(lblId, gbc);
gbc.gridx++;
txtId = new JTextField(20);
txtId.setEditable(false);
panel.add(txtId, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = 2;
btnSubmit = new JButton("Submit");
btnSubmit.addActionListener(new SubmitListener());
panel.add(btnSubmit, gbc);
return panel;
}
public class SubmitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtName.requestFocus();
txtProg.setText("");
txtId.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") &&
txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
ID_COUNTER++;
txtId.setText("" + ID_COUNTER);
btnSubmit.setText("Confirm");
}
}
}
}
}
Edited to add: If you want the title JLabel to be right-justified, you'll have to switch to a BorderLayout. I added an empty border so the text wouldn't be on the right edge of the JFrame.
Here's the changed method.
private JPanel createTitlePanel(String title) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
JLabel lblTitle = new JLabel(title);
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle, BorderLayout.AFTER_LINE_ENDS);
return panel;
}
I'm creating a gui with java swing who is supposed to be implemented on an LCD touch screen. The gui will take all the screen and is not supposed to be closable. So "setUndecorated(true)" is essential.
Problem, when I'm using it, all the content of the frame is not displaying, only the buttons appears when I'm moving my mouse over them. Then all the content appears when I maximise and minimise the frame.
Here is the code I'm using :
public static void main(String[] args) {
//Création de notre JFrame
fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setSize(800, 600);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
support = new JPanel();
///////Adding content to the JPanel()/////////////
fenetre.setContentPane(support);
fenetre.setUndecorated(true);
fenetre.setVisible(true);
}
The only solution I've find so far is to change the size of the frame after set the frame visible like so :
fenetre.setSize(801, 601);
fenetre.setSize(800, 600);
But I'm not really correcting the problem, just getting around it.
(EDIT)
My appologies for that uncomplete code.
Here is a complete exemple that you can test yourself.
First test it with undecorated to false, then try with undecorated to true and visualise the content of the window by maximising and minimising the gui.
Finally, try it with the Quick fix in the bottom of the code.
the code :
package test;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class test {
//Declarations
private static JFrame fenetre;
private static JPanel support;
private static JLabel l1, l2;
private static JComboBox<String> c1, c2;
private static JButton b1, b2;
//List to initiate the comboBoxes
private static String[] listC1 = {"Peter", "Alex", "Jhon", "Bran"};
private static String[] listC2 = {"10", "20", "32", "45"};
public static void main(String[] args) {
//Initialisation of the JFrame
fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setSize(800, 600);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
//Initialisation of the JPanel
support = new JPanel();
support.setBackground(Color.red);
support.setPreferredSize(fenetre.getSize());
//Initialisation of the components
l1 = new JLabel("What's my name");
l2 = new JLabel("What's my age");
c1 = new JComboBox<String>(listC1);
c2 = new JComboBox<String>(listC2);
b1 = new JButton("validate name");
b2 = new JButton("validate age");
//Creating layout
support.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
//Adding components
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(20, 20, 0, 0);
gbc.gridx = 0;
gbc.gridy = 0;
support.add(l1, gbc);
gbc.gridy = 1;
support.add(c1, gbc);
gbc.insets = new Insets(20, 20, 20, 0);
gbc.gridy = 2;
support.add(b1, gbc);
gbc.insets = new Insets(20, 20, 0, 20);
gbc.gridx = 1;
gbc.gridy = 0;
support.add(l2, gbc);
gbc.gridy = 1;
support.add(c2, gbc);
gbc.insets = new Insets(20, 20, 20, 20);
gbc.gridy = 2;
support.add(b2, gbc);
//Adding Listeners
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("My name is " + c1.getSelectedItem());
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("My age is " + c2.getSelectedItem());
}
});
//Adding the JPanel to the content pane of the JFrame
fenetre.setContentPane(support);
//Setting undecorated true (switch between true and false for testing)
fenetre.setUndecorated(false);
fenetre.setVisible(true);
//Quick fix, uncomment to test
//fenetre.setSize(801, 601);
//fenetre.setSize(800, 600);
}
}
You don't add any buttons to your JPanel so how do you expect it to display them?
Either way, here's a simple example of displaying a button:
JFrame fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setExtendedState(JFrame.MAXIMIZED_BOTH);
fenetre.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
JPanel support = new JPanel();
JButton button = new JButton("button");
support.add(button);
fenetre.setContentPane(support);
fenetre.setVisible(true);
Note that you should use a proper layout.
I also added setExtendedState(JFrame.MAXIMIZED_BOTH) to fill the screen, and setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE) as you didn't want the screen to be closable.
Problem, when I'm using it, all the content of the frame is not displaying, only the buttons appears when I'm moving my mouse over them.
Components should be added to the panel/frame BEFORE the frame is made visible.
If you add components to a visible frame, then the basic logic is:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // make sure panel is repainted
I'm a little lost here, when I run the program the buttons are in the middle of the input and not directly on the bottom aligned with it. I'm not sure what I'm doing wrong. I'm also trying to find out how to get statistics for my input like min and max value, and average word size. I'm a little lost, thanks!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.Arrays;
public class CopyTextPanel extends JPanel
{
private JTextField input;
private JLabel output, inlabel, outlabel;
private JButton compute, clear;
private JPanel panel, panel1, panel2;
public CopyTextPanel()
{
setLayout (new BoxLayout(this, BoxLayout.Y_AXIS));
inlabel = new JLabel("Input: ");
outlabel = new JLabel("Text Statistics Result: ");
input = new JTextField (50);
output = new JLabel();
compute = new JButton("Compute Statistics");
compute.addActionListener (new ButtonListener());
clear = new JButton("Clear Text");
clear.addActionListener (new ButtonListener());
panel = new JPanel();
panel1 = new JPanel();
panel2 = new JPanel();
output.setMaximumSize (new Dimension(500, 30));
output.setMinimumSize (new Dimension(500, 30));
panel.setMaximumSize (new Dimension(500, 30));
panel.setMinimumSize (new Dimension(500, 30));
panel.setBackground(Color.gray);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(inlabel);
panel.add(input);
panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS));
panel1.add(compute);
panel1.add(clear);
add (Box.createRigidArea (new Dimension(0, 10)));
panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS));
panel2.add(outlabel);
panel2.add(output);
setMaximumSize (new Dimension(600, 250));
setMinimumSize (new Dimension(600, 250));
setBackground(Color.white);
add (panel);
add (panel1);
add (panel2);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
String inputText = input.getText();//sets what is typed by the user
to a String object
String[] splitted = inputText.trim().split("\\p{javaSpaceChar}
{1,}");//makes a String array, and trims all the whitespaces from the user
input
int numberofWords = splitted.length;//it then sets splitted length
to an integer
String numow = Integer.toString(numberofWords);// finally it makes
the numberofwords int into a string
Arrays.sort(splitted);
if (event.getSource()==compute)//if the user presses the compute
button
{
output.setText (numow + " words; " );//the output is the string
of integers of how many words were typed
}
else//if the user presses another button
input.setText(" "); // clear text filed after copying
}
}
}
So based on the desired result...
I would recommend considering using a series of panels, dedicated to generating the layout requirements for each row, then wrapping those together into a single container.
For my money, GridBagLayout presents the most flexible option, while also presenting one of the more complicated at the same time.
This example focuses solely on the layout requirements, you'll have to figure out how to apply the functionality to it later.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() throws HeadlessException {
setBorder(new EmptyBorder(5, 5, 5, 5));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(2, 2, 2, 2);
JPanel fieldPane = new JPanel(new GridBagLayout());
JTextField inputField = new JTextField("Computer Science 1");
fieldPane.add(new JLabel("Input Text:"), gbc);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
fieldPane.add(inputField, gbc);
JPanel buttonPane = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.insets = new Insets(2, 2, 2, 2);
buttonPane.add(new JButton("Computer Statistics"), gbc);
gbc.anchor = GridBagConstraints.LINE_START;
gbc.weightx = 1;
buttonPane.add(new JButton("Clear Text"), gbc);
JPanel resultsPane = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.insets = new Insets(2, 2, 2, 2);
resultsPane.add(new JLabel("Text Statistics Result:"));
gbc.anchor = GridBagConstraints.LINE_START;
gbc.weightx = 1;
resultsPane.add(new JLabel("3 words"), gbc);
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(fieldPane, gbc);
add(buttonPane, gbc);
add(resultsPane, gbc);
}
}
}
I strongly recommend having a look at Laying Out Components Within a Container for more details about how various layout managers work
You should use Layouts such as BorderLayout that might help you.
Change the JPanels by doing panel.add(new JButton("East"),BorderLayout.EAST);
etc.. I hope it helps. If you dont use layouts they will end up randomized.
So I'm trying to copy the layout of this website.
Website Pinterest Log In
Here's some what I have already done.
I'm using "null" for my layout.
I also put an actionlistener on my button which shows another frame.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame {
public static void main (String [] args) {
JFrame frame = new JFrame("Pinterest");
frame.setVisible(true);
frame.setSize(1300,750);
JPanel panel = new JPanel();
frame.add(panel);
JLabel name = new JLabel("Log in to Pinterest");
name.setBounds(500, 96, 300, 100);
name.setFont(new Font("Tahoma", Font.PLAIN, 28));
JTextField text1 = new JTextField(15);
text1.setBounds(500, 450, 300, 40);
JTextField text2 = new JTextField(15);
text2.setBounds(500, 350, 300, 40);
JButton button = new JButton("Log In");
button.setBounds(560,550, 200,30 );
panel.setLayout(null);
panel.add(name);
panel.add(text1);
panel.add(text2);
panel.add(button);
button.addActionListener(new Action1());
}
static class Action1 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JFrame frame2= new JFrame("Pinterest");
frame2.setVisible(true);
frame2.setSize(1300,750);
}}
Every time I would run this in my JCreator it would only show my frame. Then I have to maximize it to view the components but after I maximize it then minimize it doesn't hide anymore.
After I maximize the frame.
What is wrong with my code?
Does my code works on yours smoothly? does it shows?
How can I hide the first frame after clicking the button?
I'm having a hard time putting icon on the frame too.
Thanks for the help.
There are a number of basic mistakes
null layouts. Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
Making the frame visible before you've finished updating the UI. In most cases this can be fixed with revalidate, but since that causes the layout managers to recalculate their layouts, it's pointless when you're using null layouts
The simple answer is, use layout managers. The longer answer is more complicated.
You have three distinct areas, the "login with" group, the "field" group and (what I like to term) the "action" group. Each of these have there own requirements and functionality, it's best to try a seperate them if you can.
This will allow to apply functionality to each group or class which is unique to that group/class and reduce a lot of management head aches
The following examples focus on the layout, it does not focus on how you would then connect the functionality, this would be achieved simply through the use of an Observer Pattern, perhaps like ActionListener
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LoginPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LoginPane extends JPanel {
public LoginPane() {
setBackground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 20, 4, 20);
JLabel title = new JLabel("Log in to Pinterest");
title.setFont(title.getFont().deriveFont(Font.BOLD, 18f));
title.setBorder(new EmptyBorder(10, 0, 10, 0));
add(title, gbc);
add(new GroupPane(), gbc);
gbc.insets = new Insets(4, 0, 4, 0);
add(new JSeparator(JSeparator.HORIZONTAL), gbc);
gbc.insets = new Insets(4, 20, 4, 20);
add(new FieldPane(), gbc);
gbc.insets = new Insets(4, 0, 0, 0);
add(new ActionPane(), gbc);
}
}
public class GroupPane extends JPanel {
public GroupPane() {
setOpaque(false);
JPanel fbPane = new JPanel();
JPanel goPane = new JPanel();
JPanel twPane = new JPanel();
fbPane.setBackground(Color.RED);
goPane.setBackground(Color.BLUE);
twPane.setBackground(Color.CYAN);
fbPane.add(makeLabel("Log in with Facebook"));
goPane.add(makeLabel("Log in with Google"));
twPane.add(makeLabel("Log in with Twitter"));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 0, 4, 0);
add(fbPane, gbc);
add(goPane, gbc);
add(twPane, gbc);
}
protected JLabel makeLabel(String text) {
JLabel label = new JLabel(text);
label.setForeground(Color.WHITE);
label.setFont(label.getFont().deriveFont(Font.BOLD, 14f));
return label;
}
}
public class FieldPane extends JPanel {
private JTextField email;
private JPasswordField password;
public FieldPane() {
setOpaque(false);
email = new JTextField(10);
password = new JPasswordField(10);
email.setBackground(new Color(225, 225, 225));
password.setBackground(new Color(225, 225, 225));
Font font = email.getFont().deriveFont(Font.PLAIN, 24f);
email.setFont(font);
password.setFont(font);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(4, 0, 4, 0);
add(email, gbc);
add(password, gbc);
JLabel label = new JLabel("Are you a business? Get started here");
label.setFont(label.getFont().deriveFont(Font.PLAIN, 10f));
gbc.insets.left = 4;
add(label, gbc);
}
}
public class ActionPane extends JPanel {
public ActionPane() {
setBorder(new EmptyBorder(10, 20, 10, 20));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.insets = new Insets(4, 4, 4, 4);
gbc.anchor = GridBagConstraints.WEST;
add(makeLabel("Forgot your password?"), gbc);
gbc.gridy++;
add(makeLabel("Sign up now"), gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.gridheight = 2;
gbc.ipady = 10;
gbc.anchor = GridBagConstraints.EAST;
JButton login = new JButton("Log in");
add(login, gbc);
}
protected JLabel makeLabel(String text) {
JLabel label = new JLabel(text);
label.setForeground(Color.DARK_GRAY);
return label;
}
}
}
Take a look at Laying Out Components Within a Container and How to Use GridBagLayout. The LoginPane could also make use of a GridLayout, see for more details
I am thoroughly confused. I have a pretty decent understanding of how each layout manger works and what each one is used for, but I'm not understanding what combination of layout managers and JPanels are necessary to make what I need work.
What I am trying to accomplish
I have a top bar, and a bottom bar of a container panel NORTH and SOUTH of a BorderLayout.
Within the Center panel, I want an unknown number of buttons 1 or more. Regardless of how many buttons there are they all need to be the same size, if there are dozens then scrolling should start happening once the buttons pass the window size limit.
What I am getting
Depending on the combination of layout mangers and how many nested JPanels I use and all sorts of trouble shooting, I get one massive button filling the entire CENTER element. I get 2 buttons that are the right size, but spread way apart (gap filling the CENTER space), or I get a dozen buttons that are the right size with no scroll.
I can solve any one of these, but then the other breaks. IE if I get a bunch of correctly sized buttons that properly scroll, then when I replace them with a single button its one massive button. Or if I get a single properly sized button then the larger quantity won't scroll etc.
My Code
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.io.*;
public class TestCode extends JFrame {
private final JFrame frame;
public TestCode(){
frame = new JFrame();
JLabel title = new JLabel("Test Title");
JPanel windowContainer = new JPanel();
JPanel topPanel = new JPanel();
final JPanel middlePanel = new JPanel();
JPanel bottomPanel = new JPanel();
JButton searchButton = new JButton("Search");
JButton browseButton = new JButton("Browse...");
JButton testButton = new JButton("Button 1");
JButton exitButton = new JButton("Exit");
final JTextField searchBar = new JTextField("Search database...");
topPanel.setLayout(new GridLayout(2,0));
topPanel.add(title);
title.setHorizontalAlignment(JLabel.CENTER);
topPanel.setPreferredSize(new Dimension(getWidth(), 100));
// This is a subset of the top section. Top part is two panels, bottom panel is two cells (grid)
JPanel topPanelSearch = new JPanel();
topPanelSearch.setLayout(new GridLayout(0,2));
topPanelSearch.add(searchBar);
topPanelSearch.add(searchButton);
topPanel.add(topPanelSearch);
// PROBLEM AREA STARTS
// middlePanel.setLayout(new FlowLayout());
middlePanel.setLayout(new GridLayout(0, 1, 10, 10));
// middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.PAGE_AXIS));
JPanel innerContainer = new JPanel();
innerContainer.setLayout(new BoxLayout(innerContainer, BoxLayout.PAGE_AXIS));
// innerContainer.setLayout(new FlowLayout());
// innerContainer.setLayout(new GridLayout(0, 1, 10, 10));
for(int i = 0; i < 2; i++){
JButton button = new JButton("Button ");
button.setPreferredSize(new Dimension(400, 100));
JPanel test = new JPanel();
test.add(button);
innerContainer.add(test);
}
JScrollPane midScroll = new JScrollPane(innerContainer);
middlePanel.add(midScroll);
// PROBLEM AREA ENDS
bottomPanel.setLayout(new GridLayout(0, 3));
bottomPanel.setPreferredSize(new Dimension(getWidth(), 100));
bottomPanel.add(testButton);
bottomPanel.add(browseButton);
bottomPanel.add(exitButton);
windowContainer.setLayout(new BorderLayout());
windowContainer.add(topPanel, BorderLayout.NORTH);
windowContainer.add(middlePanel, BorderLayout.CENTER);
windowContainer.add(bottomPanel, BorderLayout.SOUTH);
frame.add(windowContainer);
frame.setTitle("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(480, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args){
TestCode test = new TestCode();
}
}
Visual of some of the fail results
I want the leftmost picture, but buttons should be stacked neatly (like the middle picture) when there are only a few results, and scrollable when there are lots.
What am I doing wrong?
Try with GridBagLayout and a filler component that takes the remaining vertical space and therefore forces the buttons upwards.
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.Box.Filler;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class GridbagButtons extends JFrame {
private final JScrollPane jscrpButtons;
private final JPanel jpButtons;
public GridbagButtons() {
setLayout(new BorderLayout());
jpButtons = new JPanel(new GridBagLayout());
jscrpButtons = new JScrollPane(jpButtons);
add(jscrpButtons, BorderLayout.CENTER);
// add a custom number of buttons
int numButtons = 10;
for (int i = 0; i < numButtons; i++) {
JButton jbButton = new JButton("Button");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = i;
jpButtons.add(jbButton, gbc);
}
// add a vertical filler as last component to "push" the buttons up
GridBagConstraints gbc = new GridBagConstraints();
Filler verticalFiller = new Filler(
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, Integer.MAX_VALUE));
gbc.gridx = 0;
gbc.gridy = numButtons;
gbc.fill = java.awt.GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
jpButtons.add(verticalFiller, gbc);
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridbagButtons().setVisible(true);
}
});
}
}