Grid Layout Java - java

I have created a java program that shows a grid of buttons and labels and i want to know how to pit a constraint on the labels and buttons so they dont re-size when window is dragged out.. can anyone help please?
this is my gridlayout class
package JFrameTester;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class layout extends JFrame {
JButton button1,button2,button3;
JLabel label1,Label2,Label3;
public layout (){
setLayout(new GridLayout(2, 2));
button1 = new JButton ("button1");
add(button1);
label1 = new JLabel ("label1");
add(label1);
button2 = new JButton ("button1");
add(button2);
Label2 = new JLabel ("Label2");
add(Label2);
button3 = new JButton ("button1");
add(button3);
Label3 = new JLabel ("Label3");
add(Label3);
}
}
and this is my main class
public class JFrameTester {
/**
* #param args
*/
public static void main(String[] args) {
layout Lay = new layout();
Lay.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Lay.setVisible(true);
// JFrame frame = new JFrame("BUY COMPUTER");
Lay.setSize(800, 600);
//frame.pack();
// frame.setVisible(true);
Lay.addWindowListener(new MyWindowListener());
}
}

Place the labels and buttons inside a JPanel, and then add that JPanel to your GridLayout. GridLayout automatically resizes components to fit the size of the cell they are placed in and when a JFrame is resized it will adjust the components size as needed. If you place them in JPanels only the JPanel in that cell will be resized, not the components.
EDIT
In addition to that it's Java practice to name all classes with an uppercase letter, your layout should be Layout. However, the name Layout does not accurately convey the purpose of class Layout as your class is not a layout, it's a JFrame. Perhaps LayoutFrame would be a better class name.
And (this is default Java practice) variables should be camelcase, beginning with a lowercase letter and subsequent words having a capital letter e.g. thisIsAVariable. Alternatively you could use underscores which is not normal Java practice, this_is_a_varaible. Given that in Java classes generally start with a capital letter and variables start with a lowercase letter the statement layout Lay = new layout(); looks very strange and a bit confusing at first glance.

Related

Keeping components horizontally aligned using a flow layout manager

For reasons I won't discuss in detail, I am limited to using a flow layout manager. The obvious problem with this and my necessity to keep components on the same line, is that it pushes components further down the frame is they surpass the panel edges.
Are there methods I can use to align components to make sure that labels and their corresponding text fields appear on the same line?
If I have understood correctly, the main problem is that the label and the input are separated (the label on the right side, and the input in the next line on the left).
One solution for that problem is the group the label and the input field into a sub panel, and add this sub panel to the main panel which uses the FlowLayout.
The code below illustrates this technique:
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
*
* #author acampos
*/
public class Main02 {
public static void main(String[] args) {
JFrame jFrame = new JFrame();
JPanel mainPanel = new JPanel();
JPanel dynamicPanel;
JLabel dynamicLabel;
JTextField dynamicInput;
for (int i = 0; i < 5; i++) {
// Creates the panel that will contain the Label AND the Input
dynamicPanel = new JPanel();
// Creates the dynamic label
dynamicLabel = new JLabel("Label " + i + ": ");
// Creates the dynamic text field
dynamicInput = new JTextField(10);
// Adds the label and the text field to the dynamic panel
dynamicPanel.add(dynamicLabel);
dynamicPanel.add(dynamicInput);
dynamicPanel.setSize(100, 100 );
// Adds the dynamic panel to the main panel <-- HERE IS THE KEY
mainPanel.add(dynamicPanel);
}
// Set the FlowLayout to the MAIN PANEL, so the dynamic panels
// will 'flow' but the label and the text field will be kept together
mainPanel.setLayout(new FlowLayout(3));
// Adds the main panel (which contains the dynamic panels) to the main frame
jFrame.add( mainPanel );
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
jFrame.setSize(600, 150);
jFrame.setResizable(true);
}
}
When you run this code (yes, you can run it) and change the jFrame's size you see that the label and the input don't split anymore.
Note: For the next questions, I strongly suggest you that you share your code with the community. That's a good practice that is more detailed on https://stackoverflow.com/help/how-to-ask

Layout - Relative to screensize

So I am a computer science student and I've finished my first year. I wanted to create a simple program and I realized that I am so tired of using no layout;
this.setLayout(null);
It is so tiresome to add bounds to every single component. Well, I have been using JPanel components and GridLayout a lot, which have made my work a bit easier. But I am tired of it.
I care very much about the look of the GUI I make and use almost half the time programming to make the GUI look good before I start adding the functionality of the code. By not using a layout and adding bounds I am forced to setResizable(false) because it looks bad if I change the size of the JFrame.
I've been searching a bit, and I know of BorderLayout, and FlowLayout, but I don't like them. Is there any Layout that keeps the relative size of the components with respect to the size of the window?
For example I want to make a simple program that looks like this: (Quick sketch in Photoshop)
I can easily make this with 3 panels, but as I said, if I change the size of the frame everything stays in place instead of being relative to the window-size.
Can you guys help me?
This design looks for me to fit the BorderLayout, where in the NORTH you have the values that changes the CENTER you have the main part, and the SOUTH you have the buttons.
Link to the Oracle Border Layout
You can apply this BorderLayout to the JFrame, then create 3 JPanels for each of the NORTH,CENTER and SOUTH sections. If you want to use responsive design for the components and panels, take a look at GridBagLayout which is much more flexible than the GridLayout
Layout management is a very complex problem, I don't think people really appreciate just how complex it really is.
No one layout is ever going to achieve everything your want, in most cases, you will need to resort to two or more layouts, especially as your requirements become more complex.
For example, the following is simply a BorderLayout at the base and the buttons on a JPanel using a FlowLayout
Which is achieved by using
JList listOfThings = new JList(...);
JTextField tf = new JTextField();
JButton add = new JButton("Add");
JButton delete = new JButton("Delete");
JButton go = new JButton("Go...");
JPanel buttons = new JPanel();
buttons.add(add);
buttons.add(delete);
buttons.add(go);
add(new BorderLayout());
add(tf, BorderLayout.NORTH);
add(new JScrollPane(listOfThings));
add(buttons, BorderLayout.SOUTH);
For more complex layouts, I would consider using something like GridBagLayout. You may also want to consider MigLayout as an alternative
Take a look at Laying Out Components Within a Container for more details about using layout managers
I'd like to use the combination of BorderLayout and BoxLayout. BorderLayout let me put the component based on their relative location's relation and BoxLayout let me manage the subtle distance ( create some white space). You can use component.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); to achieve this goal too.
Here is a demo and hope it can help you.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class LayoutTest{
private JTextField jTextField;
public void createUI(){
JFrame frame = new JFrame("Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(new TextFieldPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ListPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ButtonPanel());
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
LayoutTest layoutTest = new LayoutTest();
layoutTest.createUI();
}
#SuppressWarnings("serial")
class TextFieldPanel extends JPanel{
public TextFieldPanel(){
setLayout(new BorderLayout());
jTextField = new JTextField();
jTextField.setEditable(false);
add(jTextField,BorderLayout.CENTER);
}
}
#SuppressWarnings("serial")
class ListPanel extends JPanel implements ListSelectionListener{
private JList<String> list;
public ListPanel(){
setLayout(new BorderLayout());
String stringArr[] = new String[30];
for (int i = 0; i < 30; i++) {
stringArr[i] = "JList :This line is item" + i;
}
list = new JList<String>(stringArr);
JScrollPane scrollPane = new JScrollPane(list);
add(scrollPane,BorderLayout.CENTER);
setBackground(new Color(211,211,211));
list.addListSelectionListener(this);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
jTextField.setText(list.getSelectedValue());
}
}
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BorderLayout());
add(button1,BorderLayout.WEST);
add(button2,BorderLayout.CENTER);
add(button3,BorderLayout.EAST);
}
}
}
Here is the effect:
You can use BoxLayout for ButtonPanel if you don't want to let the button's size change.
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(button1);
add(Box.createHorizontalStrut(8));
add(button2);
add(Box.createHorizontalStrut(8));
add(button3);
}
}
And the effect is like this:
For more infomation about using BoxLayout to generate whitespace, you can refer to https://stackoverflow.com/a/22525005/3378204
Try GridBagLayout.
Your sketch is actually quite close to the one of the examples in the official tutorial.
HVLayout keeps the relative size of the components with respect to the size of the window, that is, if you configure components to have a relative size (e.g. buttons usually do not grow or shrink - they stick to their preferred size). This SO question was one of the motivations for me to push HVLayout to a release and a screenshot is included (showing big window size, smalll size and preferred "default" size):
Source code for the window is in RelativeToWindowSize.java
A number of helper-classes from HVLayout are used to build the window, so I don't think it will be of much use here, but to get an impression, the "build window" part shown below:
public RelativeToWindowSize build() {
CSize cs = new CSize();
CForm form = new CForm(new VBox(new Insets(2, 4, 2, 4)), cs);
addTitledBorder(form.get(), "Vertical box", Color.BLACK);
form.add(new JScrollPane(
tfield = new JTextArea("Value that changes with value choosen from list.\nhttp://stackoverflow.com/questions/24462297/layout-relative-to-screensize/")
)).csize().setAreaSize(1.0f, 2.5f).fixedMinHeight().setMaxHeight(4.0f);
// tfield shows mono-spaced font by default.
tfield.setFont(SwingUtils.getUIFont());
form.add(new JScrollPane(vlist = new JList<String>(getListValues())))
.csize().setAreaSize(1.0f, 5.0f);
form.addChild(new HBox());
addTitledBorder(form.get(), "Horizontal box", Color.RED);
form.addChild(new HBox(SwingConstants.CENTER));
addTitledBorder(form.get(), "Centered box.", Color.BLUE);
form.add(createButton(cs, "Add"));
form.add(createButton(cs, "Modify"));
form.up();
form.addChild(new HBox(SwingConstants.TRAILING));
addTitledBorder(form.get(), "Trailing box", Color.GREEN);
form.add(createButton(cs, "Delete"));
setContentPane(form.getRoot());
pack();
setLocationByPlatform(true);
//applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
vlist.addListSelectionListener(this);
log.debug(getClass().getName() + " build.");
return this;
}
private Component createButton(CSize cs, String text) {
// For purpose of demo, let button shrink in width.
return cs.set(new TButton(text)).setFixed().shrinkWidth(0.33f).get();
}

Last button in JFrame is set as background?

import javax.swing.JButton;
import javax.swing.JFrame;
public class Test extends JFrame {
private static final long serialVersionUID = 1L;
public Test() {
super("A test");
setSize(360,300);//Size of JFrame
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);//Sets if its visible.
JButton num1 = new JButton("1");//Set the JButton name
JButton num2 = new JButton("2");
JButton num3 = new JButton("3");
num1.setBounds(80,70,50,50);
num2.setBounds(130,70,50,50);
num3.setBounds(180,70,50,50);
add(num1);
add(num2);
add(num3);
}
public static void main (String[] args) {
new Test().setVisible(true);
}
}
Here the num3 button is set as the background, I want the buttons to be aligned. This might be a trivial mistake I'm not sure as I've just started working with JFrame. Thank you.
The Problem
Basically, there are three parts that are causing this problems...
JFrame uses a BorderLayout by default. This means that only the last component add to any one of the five available layout positions will be managed
You call setVisible(true) before adding anything to the frame
You call setBounds on the buttons.
Because the components are generally painted in z-order (in FIFO order generally) and because of the optimisation in the code, the last button is been controlled by the BorderLayout of the frame, but the other two maintain the bounds you set before
Really interesting problem
Solution(s)
Use an appropriate layout manager, maybe a FlowLayout or GridBagLayout
Call setVisible last where ever possible
Check out Laying Out Components Within a Container for details
This is because of Layout Manager. Please check the code below.
i use another JPanel to put all the buttons. i set the panel as it will have 1 row and 3 columns objects.
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test extends JFrame {
private static final long serialVersionUID = 1L;
JPanel buttonPanel;
public Test() {
super("A test");
setSize(360,300);//Size of JFrame
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);//Sets if its visible.
setLayout(null);
buttonPanel = new JPanel(new GridLayout(1, 3));
buttonPanel.setBounds(80, 70, 150, 50);
JButton num1 = new JButton("1");//Set the JButton name
JButton num2 = new JButton("2");
JButton num3 = new JButton("3");
buttonPanel.add(num1);
buttonPanel.add(num2);
buttonPanel.add(num3);
add(buttonPanel);
}
public static void main (String[] args) {
new Test().setVisible(true);
}
}
Well, never use raw placing and no Layout Manager.
This is your Bible
You can do that with some Layout tricks. For example this one:
First of all import the Layout classes.
import java.awt.GridLayout;
import java.awt.BorderLayout;
Make the frame a BorderLayout frame by copying this in the constructor of it.
setLayout(new BorderLayout());
Then make another JPanel and make it a GridLayout JPanel:
JPanel panel = new JPanel(new GridLayout(1,3));
panel.add(num1);
panel.add(num2);
panel.add(num3);
Arguments 1 and 3 mean "use exactly 1 row and 3 columns to place the widgets in this JPanel".
Finally add the last panel at the center of the frame:
add(panel,BorderLayout.CENTER);
This way you won't deal with dimensions or precise spots and still do what you want...
(to test it copy all the code in "Test" constructor)

Java Swing spacing between objects

I have a Java program where i would prefer if i could get a very specific layout.
This is what I get:
JLabel JToggleButon JLabel JToggleButon
This is what I want:
JLabel JToggleButon
JLabel JToggleButon
This is the code:
package Main;
import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
public class SystemWindow {
static JFrame window = new JFrame("System statistics");
static JToggleButton button = new JToggleButton("Push me");
static JLabel status = new JLabel("Status: ");
static JLabel status2 = new JLabel("Status: ");
static JToggleButton button2 = new JToggleButton("Push me");
static FlowLayout layout = new FlowLayout();
public static void openWindow(){
window.setLayout(new GridBagLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(status);
window.add(button);
window.add(status2);
window.add(button2);
window.setSize(100, 100);
window.pack();
window.setSize(200,70);
window.setVisible(true);
while(true){
status.setText("Status: "+button.isSelected());
status2.setText("Status: "+button2.isSelected());
}
}
}
p.s: Wrote the code in eclipse.
you can use GridLayout where you can specify rows, columns and spacings
i.e. add a jpanel with gridlayout and add these elements inside this panel
new JPanel(new GridLayout(2,2,5,5));
first parameter is the rows, second the columns and the others are the horizontal and vertical spacing between controls
I guess this works
JPanel panel = new JPanel(new GridLayout(2,2,5,5));
window.add(panel);
panel.add(status);
panel.add(button);
panel.add(status2);
panel.add(button2);
The behaviour you are getting is the default behaviour for FlowLayout. Read more about it here. Read morea bout layouts here and choose what you prefer.
As you are using GridBayLayout you have to provide some position constraints when adding controls to container. Here you have complete guide. 3rd party layout manager as MigLayout should suit your needs too.
while(true){
status.setText("Status: "+button.isSelected());
status2.setText("Status: "+button2.isSelected());
}
your computer is going to explode thanks to that code :)

Aligning JButton to the right

I am creating an interface in java and i want to align the button to the right. I have try but its not working. Can someone tell me how to do it?
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Button_Alignment extends JFrame{
public JPanel header,body,footer;
public JButton add1;
public JButton save;
public Button_Alignment(){
super("BUTTON");
GridLayout g1 = new GridLayout(3,1);
setLayout(g1);
//////
header = new JPanel();
JButton add1 = new JButton("add");
header.add(add1);
JButton save = new JButton("save");
header.add(save);
//////
add(header);
header.setBackground(Color.cyan);
}
public static void main(String[] args){
Button_Alignment ba = new Button_Alignment();
ba.setSize(400, 400);
ba.setVisible(true);
}
}
Your current layout manager (GridLayout) is being created with 3 rows and a single column. Hence, the components you add to the JFrame will appear vertically from top to bottom. Worse still, GridLayout will aportion space equally amongst all 3 components, meaning that your buttons will stretch in both directions, which is almost certainly not what you require.
I would consider using an alternative layout manager. For simple layouts I tend to favour BorderLayout or FlowLayout. For more complex layouts I lean towards GridBagLayout although there are others who prefer MigLayout.
More information here.
Try like this:
JButton save = new JButton ("save");
setLayout (new BorderLayout ());
add (save, BorderLayout.EAST);
you set GridLayout to the JFrame constructor instead of JPanel (JPanel has by default FlowLayout), I think that
header.setLayout(new GridLayout(3,1));
header.add(add1);
header.add(save);
notice ---> but GridLayout in current ComponentOrientations to start from left to right, then 3rd. grid is empty
then only to add JFrame#add(JPanel), in your case
add(header);
A quick and dirty way is to put the button [or a container immediatly wrapping the button, if you want to add other components on the right next to your button] it in a container that uses the BorderLayout and use the BorderLayout.EAST layout constraint for that button [or wrapping container].

Categories