java GUI layout suggestion - java

public class AFS {
public JPanel afs(final Fields input){
JPanel titlePanel = new JPanel();
//Title fields
JLabel afs = new JLabel("Statement", Label.LEFT);
Label mm = new Label("month ", Label.LEFT);
Label my = new Label("Year ", Label.LEFT);
//first line
titlePanel.add(afs);
titlePanel.add(mm);
titlePanel.add(input.MENTRY);
titlePanel.add(my);
titlePanel.add(input.YENTRY);
titlePanel.setPreferredSize(null);
//Left Panels
JPanel sb = new JPanel();
JPanel entry = new JPanel();
entry.setLayout(new BoxLayout(entry, BoxLayout.Y_AXIS));
entry.setAlignmentX(Component.LEFT_ALIGNMENT);
entry.add(new Label("Service "));
entry.add(input.s);
entry.add(new Label("Amount "));
entry.add(input.a);
entry.add(new Label("Counter "));
entry.add(input.o);
entry.add(new Label("Division "));
entry.add(input.d);
sb.add(entry);
JPanel holderPanel = new JPanel();
holderPanel.setLayout(new BoxLayout(holderPanel, BoxLayout.Y_AXIS));
holderPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
holderPanel.add(titlePanel);
holderPanel.add(sb);
JButton start = new JButton("Save Current");
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ScriptAction action = new ScriptAction();
action.saveAll(input,1);
}
});
holderPanel.add(start);
return holderPanel;
}
I have a short version of what looks like above code.
The current layout looks like this:
But I want the layout look like (paint edited).
I have tried swap using gridLayout for the entry and it will display 2 rows but gridlayout will still align everything in the center (include the title and the header). Furthermore the button span would be across the entire bottom section. I was wondering if there are any suggested way to do this?

You would need to use a combination of layout managers to achieve the desired output:
Before resize / After resize
In this case there are 3 main parts:
Top pane (Uses Box to align some text on the left and some on the right)
Middle pane (Uses GridBagLayout to position the components as in the image, maybe GridLayout with proper insets might work as well)
Bottom pane (Uses default JPanel's layout: FlowLayout)
The top pane uses 2 JPanels as well, the first one for the label Statement alone and other with FlowLayout aligned to the right for the other 4 components, as per this answer BoxLayout does not respect the preferred size of our JTextFields. So a workaround is to wrap them inside another JPanel and then wrap that JPanel along with the Statement label.
A similar problem arises with the middle pane, which needs to use 2 JPanels: One for the fields wrapped inside another bigger one which holds it and the JButton at the bottom (Save Current). We could achieve a similar output by adding the JButton with a gridx = 2 and gridy = 2 with the counter and division label and fields on gridx = 3 and gridx = 4 respectively (instead of 2 & 3) but we would then need to add gbc.insets to add insets to the top and bottom with high values as well... It's up to you which one to use :)
The code that produces the above outputs is the following:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.Box;
import javax.swing.BoxLayout;
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 FormSample {
private JFrame frame;
private JPanel topRightPane;
private JPanel centerPane;
private JPanel centerWithButtonPane;
private JPanel buttonsPane;
private JTextField monthField;
private JTextField yearField;
private JTextField serviceField;
private JTextField amountField;
private JTextField counterField;
private JTextField divisionField;
private static final int LEFT_MARGIN = 50; //Increase / Decrease to add extra space between components
private static final int RIGHT_MARGIN = LEFT_MARGIN;
//Change insets accordingly to add extra space between components (top, left, bottom, right)
private static final Insets leftInsets = new Insets(0, LEFT_MARGIN, 0, 0);
private static final Insets rightInsets = new Insets(0, 0, 0, RIGHT_MARGIN);
private static final Insets defaultInsets = new Insets(0, 0, 0, 0);
private JButton saveCurrentButton;
private JButton saveAllButton;
private JButton resetButton;
public static void main(String[] args) {
SwingUtilities.invokeLater(new FormSample()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
monthField = new JTextField(10);
yearField = new JTextField(10);
serviceField = new JTextField(10);
amountField = new JTextField(10);
counterField = new JTextField(10);
divisionField = new JTextField(10);
saveCurrentButton = new JButton("Save Current");
saveAllButton = new JButton("Save all");
resetButton = new JButton("Reset");
buttonsPane = new JPanel();
topRightPane = new JPanel();
topRightPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
topRightPane.add(new JLabel("Month"));
topRightPane.add(monthField);
topRightPane.add(new JLabel("Year"));
topRightPane.add(yearField);
centerWithButtonPane = new JPanel();
centerWithButtonPane.setLayout(new BoxLayout(centerWithButtonPane, BoxLayout.PAGE_AXIS));
Box box = Box.createHorizontalBox();
box.add(new JLabel("Statement"));
box.add(Box.createHorizontalGlue());
box.add(topRightPane);
centerPane = new JPanel();
centerPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = defaultInsets;
centerPane.add(new JLabel("Service"), gbc);
gbc.gridx = 1;
gbc.insets = rightInsets;
centerPane.add(serviceField, gbc);
gbc.gridx = 2;
gbc.insets = leftInsets;
centerPane.add(new JLabel("Counter"), gbc);
gbc.gridx = 3;
gbc.insets = defaultInsets;
centerPane.add(counterField, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.insets = defaultInsets;
centerPane.add(new JLabel("Amount"), gbc);
gbc.gridx = 1;
gbc.insets = rightInsets;
centerPane.add(amountField, gbc);
gbc.gridx = 2;
gbc.insets = leftInsets;
centerPane.add(new JLabel("Division"), gbc);
gbc.gridx = 3;
gbc.insets = defaultInsets;
centerPane.add(divisionField, gbc);
saveCurrentButton.setAlignmentX(Component.CENTER_ALIGNMENT); //Force centered alignment for our JButton
centerWithButtonPane.add(centerPane);
centerWithButtonPane.add(saveCurrentButton);
buttonsPane.add(saveAllButton);
buttonsPane.add(resetButton);
frame.add(box, BorderLayout.NORTH);
frame.add(centerWithButtonPane, BorderLayout.CENTER);
frame.add(buttonsPane, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Also please follow the advices given by #SergiyMedvynskyy about not mixing AWT and Swing components (i.e. JTextField with TextField) and only use Swing components as AWT ones are buggy.

Related

How do I center label and button?

I want my Game to look like this:
but it wont and I don't know why.. everything just doesn't go in the places I want it to be.
Could someone help me? What am I doing wrong?
It looks like this:
The color-changing isn't the problem.. its just where all the stuff is located.
package view;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class WelcomeScreen extends JFrame{
JButton button;
JLabel label;
ActionListener action;
GridBagLayout gb = new GridBagLayout();
public <button> WelcomeScreen(ActionListener action){
JPanel panel = new JPanel();
this.setSize(800,600);
GridBagConstraints gcon = new GridBagConstraints();
gcon.weightx = 1;
gcon.weighty = 1;
gcon.fill = GridBagConstraints.HORIZONTAL;
gcon.insets = new Insets(5,5,5,5);
button = new JButton("Start");
button.setPreferredSize(new Dimension(200, 50));
button.setFont(new Font("Arial", Font.PLAIN, 20 ));
button.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 2));
button.setHorizontalAlignment(SwingConstants.LEFT);
label = new JLabel("Game");
label.setPreferredSize(new Dimension(200, 50));
label.setFont(new Font("Arial", Font.PLAIN, 60 ));
this.action = action;
panel.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10));
panel.setLayout(gb);
//label
gcon.gridx = 2;
gcon.gridy = 0;
//gcon.gridwidth = 4;
//gcon.gridheight = 1;
gb.setConstraints(label,gcon);
panel.add(label);
//button
gcon.gridx = 2;
gcon.gridy = 1;
//gcon.gridwidth = 2;
//gcon.gridheight = 1;
gb.setConstraints(button,gcon);
panel.add(button);
this.add(panel,BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Start");
this.setVisible(true);
button.addActionListener(action);
}
}
As I understand you want the label and the button to be centered in the frame.
For this purpose do not set weightx and weighty since they will tell to layout manager to expand to the available space.
So remove
gcon.weightx = 1;
gcon.weighty = 1;
then, replace the following code
//label
gcon.gridx = 2;
gcon.gridy = 0;
//gcon.gridwidth = 4;
//gcon.gridheight = 1;
gb.setConstraints(label,gcon);
panel.add(label);
//button
gcon.gridx = 2;
gcon.gridy = 1;
//gcon.gridwidth = 2;
//gcon.gridheight = 1;
gb.setConstraints(button,gcon);
panel.add(button);
with this
//label
gcon.gridx = 0;
gcon.gridy = 0;
panel.add(label, gcon);
//button
gcon.gridx = 0;
gcon.gridy = 1;
panel.add(button, gcon);
Since no row and column has weight greater than 0 the layout manager will automatically place the label-button block in the middle.
Complete code
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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.SwingConstants;
public class WelcomeScreen extends JFrame{
JButton button;
JLabel label;
ActionListener action;
GridBagLayout gb = new GridBagLayout();
public <button> WelcomeScreen(ActionListener action){
JPanel panel = new JPanel();
this.setSize(800,600);
GridBagConstraints gcon = new GridBagConstraints();
gcon.fill = GridBagConstraints.HORIZONTAL;
gcon.insets = new Insets(5,5,5,5);
button = new JButton("Start");
button.setPreferredSize(new Dimension(200, 50));
button.setFont(new Font("Arial", Font.PLAIN, 20 ));
button.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 2));
button.setHorizontalAlignment(SwingConstants.CENTER);
label = new JLabel("Game");
label.setPreferredSize(new Dimension(200, 50));
label.setFont(new Font("Arial", Font.PLAIN, 60 ));
this.action = action;
panel.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10));
panel.setLayout(gb);
//label
gcon.gridx = 0;
gcon.gridy = 0;
panel.add(label, gcon);
//button
gcon.gridx = 0;
gcon.gridy = 1;
panel.add(button, gcon);
this.add(panel,BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Start");
this.setVisible(true);
button.addActionListener(action);
}
public static void main(String[] args) {
new WelcomeScreen(null).setVisible(true);
}
}
If you're willing to use Libraries I can recommend MigLayout.
Solution:
With MigLayout the code looks a bit more readable and it's generally easier:
JPanel contentPane = new JPanel(new MigLayout("", "[grow, center]", "[grow, center]"));
JPanel panel = new JPanel(new MigLayout("wrap 1", "[grow, fill]", "[]20px[]"));
JLabel label = new JLabel("Game");
label.setFont(new Font("Arial", Font.PLAIN, 60 ));
panel.add(label);
JButton button = new JButton("Start");
button.setFont(new Font("Arial", Font.PLAIN, 20 ));
button.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 2));
button.setHorizontalAlignment(SwingConstants.LEFT);
panel.add(button);
contentPane.add(panel);
setContentPane(contentPane);
Explanation:
The 'panel' is still the JPanel holding the components. The content is controlled by the layouts contraints:
The first argument of its MigLayout are the layout contrains and in that case it just auto wraps to the next line after each added component.
The second argument are the column contraints. Here it makes sure that the 'cells' (the layout manager works like a table) expand with 'grow' and the component inside that cell fill the whole cell with 'fill'.
The third argument are the row constraints. Here they just defines the gap between the rows. The '[]' in the column & row contrains stand for a column / row respectively. Anything inside that bracket defines how the cell and its content behaves, anything outside the brackets is used for defining gaps.
The 'contentPane' just makes sure that the 'panel' is centered inside using the same methods described above. It can then be added to a bigger component (like a frame) and expand, still keeping the content centered.
You should find all the info abould the Layouts capabilities at http://www.miglayout.com/whitepaper.html

GridBagLayout strange behaviour

I wrote this simple class to test GridBagLayout.
My scope was to put some buttons in diagonal into panel, using grid bag layout and setting gridx and gridy, but I have a strange behaviour.
If I put gridwidth = 2 on button "2", button "3" will be drawn under button labeled "2".
My class is a simple demo, but I cant figure out what is wrong with it
Guess Why?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test extends JFrame {
private JPanel panel;
private JButton b1;
private JButton b2;
private JButton b3;
private JButton b4;
private JButton b5;
private JLabel label1;
public Test() {
panel = new JPanel();
panel.setLayout(new GridBagLayout());
panel.setBackground(Color.DARK_GRAY);
GridBagConstraints gbc = new GridBagConstraints();
b1 = new JButton("1");
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(b1, gbc);
b2 = new JButton("2");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.gridwidth = 2;
panel.add(b2, gbc);
gbc = new GridBagConstraints();
b3 = new JButton("3");
gbc.gridx = 2;
gbc.gridy = 2;
panel.add(b3, gbc);
gbc = new GridBagConstraints();
b4 = new JButton("4");
gbc.gridx = 3;
gbc.gridy = 3;
panel.add(b4, gbc);
gbc = new GridBagConstraints();
b5 = new JButton("5");
gbc.gridx = 1;
gbc.gridy = 4;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(b5, gbc);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(500, 400);
this.setSize(800, 300);
this.setTitle("Frame principale dell'applicazione");
this.setResizable(true);
getContentPane().add(panel, BorderLayout.CENTER);
this.setVisible(true);
}
public static void main(String[] args) {
Test mioFrame = new Test();
}
}
I created the following unusual GUI
Here's what I did.
You only need one instance of GridBagConstraints.
I made all of the gridwidth values 1.
I set gbc.fill to GridBagConstraints.NONE.
Here's the code I ran.
import java.awt.BorderLayout;
import java.awt.Color;
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.SwingUtilities;
public class GridBagLayoutTestGUI extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel panel;
private JButton b1;
private JButton b2;
private JButton b3;
private JButton b4;
private JButton b5;
private JLabel label1;
public GridBagLayoutTestGUI() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Frame principale dell'applicazione");
this.panel = createMainPanel();
getContentPane().add(panel, BorderLayout.CENTER);
this.pack();
this.setLocationByPlatform(true);
this.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
panel.setBackground(Color.DARK_GRAY);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.NONE;
b1 = new JButton("1");
panel.add(b1, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
b2 = new JButton("2");
panel.add(b2, gbc);
gbc.gridx = 2;
gbc.gridy = 2;
b3 = new JButton("3");
panel.add(b3, gbc);
gbc.gridx = 3;
gbc.gridy = 3;
b4 = new JButton("4");
panel.add(b4, gbc);
gbc.gridx = 4;
gbc.gridy = 4;
b5 = new JButton("5");
panel.add(b5, gbc);
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GridBagLayoutTestGUI();
}
});
}
}
My scope was to put some buttons in diagonal into panel, using gridbaglayout and setting gridx and gridy, but I have a strange behaviour. if I put gridwidth = 2 on button "2", button "3" will be drawn under button labeled "2" .
Button 1 is added to (0, 0) // ok
Button 3 is added to (2, 2) // doesn't work
Button 3 is not added to column 2 because column 1 doesn't have a width.
Yes you tried to add:
Button 2 to (1, 1)
but the problem is when you specify a gridwidth of 2, the GridBagLayout doesn't know what the width of column 1 should be so it uses 0.
Effectively column 2 becomes column 1 and Button 3 is painted in column 1.
In general, a column doesn't have a width unless you add a component to that column with a gridwidth = 1.
If you want to randomly add components to a grid then you need to configure a minium width for each column in the GridBagLayout. See: Creating a board game layout using JLayeredPane for an example of this approach.

How to control where in my window or JFrame panels appear

this has seriously been the biggest issue in my code. I just want to create a simple pizza order taker using multiple panels. I want to be able to dictate the specific area each panel is located. Can someone please just pretend I'm a complete idiot and help me point this out?
I've attached my code as well as an image of how it looks so far. I want to be able to place individual segments like getting the user's information, choosing pizza size, then toppings, then a section where I will display the receipt with all of the order total.
I can do the calculations and take in values, I just need to figure out the appearance.
import javax.swing.*;
import java.awt.*;
public class PIZZA extends JFrame {
Container window = getContentPane();
ButtonGroup ordertype;
JRadioButton delivery, takeout;
JRadioButton small, medium, large;
JLabel fname, phonenum, zipcode;
JTextField ufname, uphonenum, uzipcode;
JPanel userinfoinput;
JPanel delivery_type;
JPanel userinfolabel;
JButton start;
BoxLayout userbox, labelbox, deliverybox;
ImageIcon starticon = new ImageIcon("start.png");
public PIZZA() {
}
public static void main(String[] args){
PIZZA frame = new PIZZA();
new PIZZA();
frame.setSize(new Dimension(600,600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("KRUSTY KRAB PIZZA");
frame.deliverymethod();
frame.getuserinfo();
frame.userinfolabels();
frame.getpizzasize();
frame.toppings_meat();
frame.setLayout(new FlowLayout());
frame.setVisible(true);
}
private void deliverymethod(){
delivery_type = new JPanel();
ordertype = new ButtonGroup();
delivery = new JRadioButton("Delivery (Currently Unavailable)");
delivery.setEnabled(false);
takeout = new JRadioButton("Take Out");
ordertype.add(takeout);
ordertype.add(delivery);
delivery_type.add(takeout);
delivery_type.add(delivery);
delivery_type.setSize(100,100);
window.add(delivery_type,BorderLayout.NORTH);
}
private void getuserinfo(){
userinfoinput = new JPanel();
//start = new JButton("Start", starticon);
//start.setLayout(null);
ufname = new JTextField(12);
uphonenum = new JTextField(12);
uzipcode = new JTextField(12);
userinfoinput.add(ufname);
userinfoinput.add(uphonenum);
userinfoinput.add(uzipcode);
//userinfoinput.add(start);
GridLayout lay = new GridLayout(3,1);
userinfoinput.setLayout(lay);
window.add(userinfoinput, BorderLayout.CENTER);
}
private void userinfolabels(){
userinfolabel = new JPanel();
fname = new JLabel("First Name");
phonenum = new JLabel("Phone Number");
zipcode = new JLabel("Zip Code");
userinfolabel.add(fname);
userinfolabel.add(zipcode);
userinfolabel.add(phonenum);
labelbox = new BoxLayout(userinfolabel, BoxLayout.Y_AXIS);
GridLayout label = new GridLayout(3,1);
userinfolabel.setLayout(label);
window.add(userinfolabel, BorderLayout.CENTER);
}
private void getpizzasize(){
JPanel pizzasize = new JPanel();
ButtonGroup size = new ButtonGroup();
small = new JRadioButton("Small");
medium = new JRadioButton("Medium");
large = new JRadioButton("Large");
size.add(small);
size.add(medium);
size.add(large);
pizzasize.add(small);
pizzasize.add(medium);
pizzasize.add(large);
pizzasize.setLayout(new FlowLayout());
pizzasize.setSize(100,100);
window.add(pizzasize, BorderLayout.SOUTH);
}
private void toppings_meat(){
JPanel meat = new JPanel();
meat.setLayout(new BoxLayout(meat, BoxLayout.Y_AXIS));
JCheckBox pepperoni = new JCheckBox("Pepperoni");
JCheckBox meatball = new JCheckBox("Meatball");
JCheckBox chicken = new JCheckBox("Grilled Chicken");
JCheckBox sausage = new JCheckBox("Italian Sausage");
JCheckBox bacon = new JCheckBox("Bacon");
meat.add(pepperoni);
meat.add(meatball);
meat.add(chicken);
meat.add(sausage);
meat.add(bacon);
window.add(meat);
}
}
This pizza GUI uses several Swing layout managers in different JPanels.
The main layout managers that I want to talk about are the JFrame BorderLayout and the input form GridBagLayout.
A BorderLayout is rather flexible in that you can put Swing components in various locations. The JPanels I created for this GUI are in the BEFORE_FIRST_LINE, CENTER, AFTER_LAST_LINE, and AFTER_LINE_ENDS positions of the BorderLayout.
The input form uses a GridBagLayout to position the JLabels and the input JTextFields in a column. The GridBagLayout is more flexible than a GridLayout because the grid cells don't have to be the same size in a GridBagLayout.
The Oracle Swing tutorial A Visual Guide to Layout Managers shows the different Swin layout managers, and how to use them.
Here's the code I used to create the pizza GUI. I created each subordinate JPanel in a separate method. All of the JFrame code is in the run method. Separating different parts of the GUI allows me to focus on one part of the GUI at a time. I can test each JPanel method separately.
I create the Swing components from left to right, top to bottom within a JPanel. This allows me to visually verify that I've included all the appropriate methods for a component. This also allows me to zero in on any component that isn't correct.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class PizzaOrdering implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PizzaOrdering());
}
#Override
public void run() {
JFrame frame = new JFrame("KRUSTY KRAB PIZZA");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(getDeliveryMethodPanel(),
BorderLayout.BEFORE_FIRST_LINE);
frame.add(getUserInformationPanel(),
BorderLayout.CENTER);
frame.add(getPizzaSizePanel(),
BorderLayout.AFTER_LAST_LINE);
frame.add(getMeatToppingsPanel(),
BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel getDeliveryMethodPanel() {
JPanel deliveryMethodPanel = new JPanel(new FlowLayout());
ButtonGroup orderTypeGroup = new ButtonGroup();
JRadioButton takeoutRadioButton =
new JRadioButton("Take Out");
orderTypeGroup.add(takeoutRadioButton);
deliveryMethodPanel.add(takeoutRadioButton);
JRadioButton deliveryRadioButton =
new JRadioButton("Delivery (Currently Unavailable)");
deliveryRadioButton.setEnabled(false);
orderTypeGroup.add(deliveryRadioButton);
deliveryMethodPanel.add(deliveryRadioButton);
return deliveryMethodPanel;
}
private JPanel getUserInformationPanel() {
JPanel userInformationPanel = new JPanel(new GridBagLayout());
userInformationPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.weightx = 1d;
JLabel nameLabel = new JLabel("First Name:");
userInformationPanel.add(nameLabel, gbc);
gbc.gridx++;
JTextField userNameField = new JTextField(20);
userInformationPanel.add(userNameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel phoneNumberLabel = new JLabel("Phone Number:");
userInformationPanel.add(phoneNumberLabel, gbc);
gbc.gridx++;
JTextField userPhoneNumberField = new JTextField(20);
userInformationPanel.add(userPhoneNumberField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel zipCodeLabel = new JLabel("Zip Code:");
userInformationPanel.add(zipCodeLabel, gbc);
gbc.gridx++;
JTextField userZipCodeField = new JTextField(20);
userInformationPanel.add(userZipCodeField, gbc);
return userInformationPanel;
}
private JPanel getPizzaSizePanel() {
JPanel pizzaSizePanel = new JPanel(new FlowLayout());
ButtonGroup sizeGroup = new ButtonGroup();
JRadioButton smallRadioButton = new JRadioButton("Small");
sizeGroup.add(smallRadioButton);
pizzaSizePanel.add(smallRadioButton);
JRadioButton mediumRadioButton = new JRadioButton("Medium");
sizeGroup.add(mediumRadioButton);
pizzaSizePanel.add(mediumRadioButton);
JRadioButton largeRadioButton = new JRadioButton("Large");
sizeGroup.add(largeRadioButton);
pizzaSizePanel.add(largeRadioButton);
return pizzaSizePanel;
}
private JPanel getMeatToppingsPanel() {
JPanel meatToppingsPanel = new JPanel();
meatToppingsPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
meatToppingsPanel.setLayout(new BoxLayout(
meatToppingsPanel, BoxLayout.Y_AXIS));
JCheckBox pepperoniCheckBox = new JCheckBox("Pepperoni");
meatToppingsPanel.add(pepperoniCheckBox);
JCheckBox meatballCheckBox = new JCheckBox("Meatball");
meatToppingsPanel.add(meatballCheckBox);
JCheckBox chickenCheckBox = new JCheckBox("Grilled Chicken");
meatToppingsPanel.add(chickenCheckBox);
JCheckBox sausageCheckBox = new JCheckBox("Italian Sausage");
meatToppingsPanel.add(sausageCheckBox);
JCheckBox baconCheckBox = new JCheckBox("Bacon");
meatToppingsPanel.add(baconCheckBox);
return meatToppingsPanel;
}
}

Gridbag Layout, Insets or anchor won't take effect

Okay, so I need your help guys. I don't know what I missed but the insets and anchor is not taking effect even though I've set the layout to GridBag.
I need to put the logout button just above the tabbedpane and position the logout button on the upper right hand corner. In other words, tabbed pane on position gridx = 0, gridy = 1; and logout Button on position gridx = 0, gridy = 0;
Also, the myaccount button, leftpanel and rightpanel which are inside the home panel, won't get the insets i applied.
What am I missing. Please help because I'm new to this layout.
TopPanel.java
package MainComponents;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.Border;
import MainTab_TabbedPane.TopTabbedPane;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
public class TopPanel extends JPanel {
//DECLARATION
JButton logOutButton = new JButton("Logout");
TopTabbedPane topTabbedPane = new TopTabbedPane();
private final Border myLineBorder = BorderFactory.createLineBorder(Color.BLACK, 2);
//CONSTRUCTOR
public TopPanel(){
setPanelInitialProperties();
addComponents();
}
//METHODS
private void setPanelInitialProperties(){
setLayout(new GridBagLayout());
setBorder(myLineBorder); //sets a Line Border for this panel
}
private void addComponents(){
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
this.add(topTabbedPane); //adds TabbedPane holding Home, Administration... to this Top Panel
gbc.gridx = 0;
gbc.gridy = 0;
this.add(logOutButton);
}
}
HomeTopPanel.java
package HomeTab;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class HomeTopPanel extends JPanel {
private final JButton MyAccountButton = new JButton("My Account");
private final JPanel leftPanel = new JPanel(new GridBagLayout());
private final JPanel rightPanel = new JPanel(new GridBagLayout());
private final Border leftPanelLineBorder = BorderFactory.createLineBorder(Color.BLACK, 2);
private final Border rightPanelLineBorder = BorderFactory.createLineBorder(Color.BLACK, 2);
//CONSTRUCTOR
public HomeTopPanel(){
constructMyAccountButton();
constructPanels();
setLeftRightPanelBorders();
this.setLayout(new GridBagLayout());
}
private void constructMyAccountButton(){
GridBagConstraints MyAccountButton_gbc = new GridBagConstraints();
MyAccountButton_gbc.gridx = 0; MyAccountButton_gbc.gridy = 0;
MyAccountButton_gbc.anchor = GridBagConstraints.NORTHWEST;
this.add(MyAccountButton);
}
private void constructPanels(){
GridBagConstraints leftPanelgbc = new GridBagConstraints();
GridBagConstraints rightPanelgbc = new GridBagConstraints();
leftPanelgbc.insets = new Insets(3,3,3,3);
leftPanelgbc.gridx = 1; leftPanelgbc.gridy = 0;
leftPanel.setPreferredSize(new Dimension(300, 500));
this.add(leftPanel);
rightPanelgbc.insets = new Insets(3,3,3,3);
rightPanelgbc.gridx = 2; leftPanelgbc.gridy = 0;
rightPanel.setPreferredSize(new Dimension(300, 500));
this.add(rightPanel);
}
private void setLeftRightPanelBorders(){
leftPanel.setBorder(leftPanelLineBorder);
rightPanel.setBorder(rightPanelLineBorder);
this.setBorder(leftPanelLineBorder);
}
}
Thanks in advanced. I'm sure there's something I missed but I don't know.
INSETS won't apply. =( ??
UPDATE:
I added the insets with the following code:
private void constructPanels(){
GridBagConstraints gbc2 = new GridBagConstraints();
gbc2.gridx = 1; gbc2.gridy = 0;
gbc2.insets = new Insets(5, 5, 5, 5);
leftPanel.setPreferredSize(new Dimension(250, 300));
this.add(leftPanel,gbc2);
gbc2.gridx = 2; gbc2.gridy = 0;
gbc2.insets = new Insets(5, 5, 5, 5);
rightPanel.setPreferredSize(new Dimension(300, 500));
this.add(rightPanel,gbc2);
}
but still not getting any inset of 5.
Apply the constraints when adding components
add(topTabbedPane, gbc);
GridBagConstraints MyAccountButton_gbc = new GridBagConstraints();
Variable names should NOT start with an upper case character. Most of your other names are correct. Then is no reason to be sloppy. Follow the Java conventions.
constructMyAccountButton();
constructPanels();
setLeftRightPanelBorders();
this.setLayout(new GridBagLayout());
The layout must be set BEFORE you add components to the panel.
GridBagConstraints MyAccountButton_gbc = new GridBagConstraints();
MyAccountButton_gbc.gridx = 0; MyAccountButton_gbc.gridy = 0;
MyAccountButton_gbc.anchor = GridBagConstraints.NORTHWEST;
//this.add(MyAccountButton); // where is the constraint?
this.add(MyAccountButton, myAccountButton_gbc);
You actually have to use the constraint.

Sizing issue with scrollable JTextField

I have a form with lots of text fields and some of those text fields may contain very long strings. To make it work I made those text fields scrollable using this code:
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension((int)textField.getPreferredSize().getWidth(), (int)textField.getPreferredSize().getHeight() * 2));
Then I put scroll into my form using GridBagLayout.
Second line in my example is required for scroller to show up. But it has downside. When I resize window to fit whole text in text field, then scroll disapears leaving me with just two times higher then others text field, which looks ridiculous.
How can I make this all work and show me normal size of text field after scroller is hidden?
EDIT:
You may use following as a demo code to reproduce the issue:
import javax.swing.*;
import java.awt.*;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension(70, 40) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("abc");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
For this , in the absence of a good SSCCE, I think you hadn't provided any constraint that goes for fill, which is used for
Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values (defined as GridBagConstraints constants) include NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but do not change its height), VERTICAL (make the component tall enough to fill its display area vertically, but do not change its width), and BOTH (make the component fill its display area entirely).
So you must add something like this to your GridBagConstraints
constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;
This will only allow it to expand HORIZONTALLY not both ways.
** EDIT : As for the added code **
Never specify setPreferredSize(...) for any component in Swing. Let the Layout Manager you are using, take care for that. Remove all setPreferredSize(...) thingies, will let it remain in normal size upon resizing.
*EDIT 2 : *
Code to tell you what I am saying :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GridBagTest extends JFrame
{
private JPanel topPanel;
private JPanel bottomPanel;
public GridBagTest()
{
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
//gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 0.8;
// Setting TOP PANEL.
topPanel = new JPanel();
topPanel.setLayout(new GridBagLayout());
GridBagConstraints constraintsTopPanel = new GridBagConstraints();
constraintsTopPanel.gridwidth = 2; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
/*
* fill with HORIZONTAL, means the component upon resize, will
* only expand along the X-Axis.
*/
constraintsTopPanel.fill = GridBagConstraints.NONE;
constraintsTopPanel.insets = new Insets(5, 5, 5, 5);
constraintsTopPanel.ipadx = 2;
constraintsTopPanel.ipady = 2;
constraintsTopPanel.weightx = 0.3;
constraintsTopPanel.weighty = 0.2;
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 0;
JTextField tfield1 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield1, constraintsTopPanel);
constraintsTopPanel.gridx = 2;
constraintsTopPanel.gridy = 0;
final JTextField tfield2 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield2, constraintsTopPanel);
constraintsTopPanel.gridx = 4;
constraintsTopPanel.gridy = 0;
JTextField tfield3 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield3, constraintsTopPanel);
topPanel.setBackground(Color.WHITE);
add(topPanel, gbc);
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 2;
constraintsTopPanel.gridwidth = 6; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
JButton button = new JButton("REMOVE");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
topPanel.remove(tfield2);
topPanel.revalidate();
topPanel.repaint();
}
});
topPanel.add(button, constraintsTopPanel);
//Setting BOTTOM PANEL.
bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
bottomPanel.setBackground(Color.DARK_GRAY);
JLabel label3 = new JLabel("I am a new JLABEL for the bottom JPanel", JLabel.CENTER);
label3.setForeground(Color.WHITE);
bottomPanel.add(label3, BorderLayout.CENTER);
gbc.weighty = 0.2;
add(bottomPanel, gbc);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String... args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridBagTest();
}
});
}
}
Well the best I've got is looking ugly in code, but does exactly what I need to the textField. Below is changed sample code from initial question. I'd be thankfull for any ideas how to make it better:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
//gbc.ipady = 20;//gives some room for scroll to appear and don't hide text area under the scroll.
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("bbbbbbbb");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
scroll.addComponentListener( new ScrollTextComponentListener(scroll, textField2));
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
class ScrollTextComponentListener implements ComponentListener {
private boolean scrollVisible;
private JScrollPane scroll;
private JComponent compareComponent;
public ScrollTextComponentListener(JScrollPane scroll, JComponent compareComponent) {
this.scroll = scroll;
this.compareComponent = compareComponent;
}
private boolean isScrollVisible() {
return scroll.getHorizontalScrollBar().getModel().getExtent() != scroll.getHorizontalScrollBar().getModel().getMaximum();
}
private void setScrollSize(){
boolean scrollVisible = isScrollVisible();
if (scrollVisible){
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
//also had to set both min and max sizes, because only preffered size didn't always work
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
}
else {
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
}
this.scrollVisible = scrollVisible;
}
#Override
public void componentResized(ComponentEvent e) {
if (isScrollVisible() != scrollVisible) setScrollSize();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
setScrollSize();
}
#Override
public void componentHidden(ComponentEvent e) {
}
}

Categories

Resources