How to set JButton size with GridBagLayout - java

I want to set the size of my JButtons that are at the center of my screen to become larger but I can't seem to find how to do that using GridBagLayouts.
Here is how it looks like :
Here is my code :
// Client
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.gridy = 5;
c.gridx = 5;
c.gridwidth = 1;
c.gridheight = 1;
c.insets = new Insets(10, 1, 1, 10);
p.add(b[0], c);
// Server
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.gridy = 10;
c.gridx = 5;
c.gridwidth = 1;
c.gridheight = 1;
c.insets = new Insets(10, 1, 1, 10);
p.add(b[1], c);
I want the buttons to take up a larger portion of the empty space around them.

More information was added: Buttons have 50% of the width and [about] 20% of the height of parent [together 50% height including the space in between]. (Slightly rewritten to match the suggestion.)
Solution
Combination of simple Layouts Layouts. Although if you do it like this you will have 3 columns or 3 rows which can't be joined, the rest can easily be changed later:
// row variation
JPanel parent = new JPanel();
parent.setLayout(new GridLayout(3, 1));
parent.add(new JPanel()); // placeholder for 1st row
JPanel row = new JPanel(); // 2nd row
row.setLayout(new GridLayout(1, 3)); // create 3 cells of equal size
row.add(new JPanel()); // 2nd row, 1st cell placeholder
// now you have a 33% x 33% (oops) rectangle in the middle
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(2, 1, 10, 10));
controls.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10);
controls.add(new JButton("Client"));
controls.add(new JButton("Server"));
row.add(controls); // add 2nd row, 2nd cell
row.add(new JPanel()); // 2nd row, 3rd cell placeholder
parent.add(row); // add 2nd row
parent.add(new JPanel()); // placeholder for 3rd row
Easy, but you won't be able to join the cells later:
JPanel parent = new JPanel();
parent.setLayout(newGridLayout(9, 9));
Bottom line: combine different layout managers, put your 2 buttons inside a panel and put some placeholders inside, then it should also work fine with GridBagLayout. That said, I would try to stay flexible by writing reusable components which can easily be combined with any layout manager. Then you don't have to use placeholders superfluous code in order to display the components correctly.
Old Answer
Alternative Solution: Use BoxLayout
BoxLayout is more intuitive and easier to understand when looking at code (of course this is only an opinion).
Decide how your window is structered (is it more like big horizontal components on top of each other PAGE_AXIS or big vertical components next to each other LINE_AXIS) and use this as the outer BoxLayout:
JPanel content = new JPanel(); // or frame
content.setLayout(new BoxLayout(content, BoxLayout.LINE_AXIS));
Add the components along the axis, where you have more than one component along the other axis use a 2nd BoxLayout. You can space components by creating rigid areas (empty rectangles always having the same size) or by adding glue (expanding like gum together with the components).
content.add(BoxLayout.createHorizntalGlue());
JPanel col = new JPanel();
col.setLayout(new BoxLayout(col, BoxLayout.PAGE_AXIS));
JButton clientBtn = new JButton("Client");
JButton serverBtn = new JButton("Server");
col.add(BoxLayout.createVerticalGlue());
col.add(clientBtn);
col.add(BoxLayout.createRigidArea(new Dimension(1, 10)));
col.add(serverBtn);
col.add(BoxLayout.createVerticalGlue());
content.add(col);
content.add(BoxLayout.createHorizontalGlue());

I can't imagine what do you want, but if you want your button to fill around, you can add
c.weightx = ...; //Specifies how to distribute extra horizontal space.
or c.weighty = ...; //Specifies how to distribute extra vertical space.

button.setMargin( new Insets(50, 50, 50, 50) );
This will add extra space to the button and allow the layout managers to do their job based on the preferred size of the button.

Related

Grid Bag Layout doesnt recognize my commands?

Im making an application that uses a lot of constructors, and I understood that you cant use the Drag and Drop tool of netbeans for making a constructor, and i thought it was good idea to learn how to code fully organized windows, anyways I read a DEITEL Java book that uses a method for adding objects to the container, here it is:
private void addobject(Component componente, int column, int row, int width
int height){
//C will be the GridBagConstraints
//And I made a new GridBagLayout called "v"
//My Panel or container is called objcontainer and the LayoutManager is v
c.gridx = column;
c.gridy = row;
c.gridwidth = width;
c.gridheight = height;
v.setConstraints(componente, c);
objcontainer.add(componente);
}
The method is declared in the same class in where the constructor is, it worked separating only by one gridy. But when I put it 2 or more away that the last object it just stays like if I put 1.
I dont know if thats how it works, also the anchors dont work perfectly, besides the LINE START one, the Center ones are failing.
Here is the code, anyways thanks:
package Windows;
import java.awt.*;
import javax.swing.*;
public class agregaringreso extends JDialog{
private int ingreso;
private String nombreingreso;
private String Frecuencia [] = {"Solo una vez", "Cada semana","Cada 2 semanas", "Cada 3 semanas", "Cada mes,"};
Container contenedor;
JPanel objcontainer;
GridBagLayout esquema;
GridBagConstraints c;
JButton aceptar;
JLabel title;
JLabel ingreso2;
JLabel nombreingreso2;
JLabel frecuencia2;
JTextField ingreso3;
JTextField nombreingreso3;
JComboBox frecuencia3;
private void addobjeto(Component componente, int columna, int fila, int ancho, int alto){
c.gridx = columna;
c.gridy = fila;
c.gridwidth = ancho;
c.gridheight = alto;
esquema.setConstraints(componente, c);
objcontainer.add(componente);
}
public agregaringreso(){
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle("Agregar Nuevo Ingreso - EkPek");
pack();
setResizable(false);
setSize(500, 200);
setLocationRelativeTo(null);
//FASE DE INICIALIZACION
contenedor = getContentPane();
objcontainer = new JPanel();
esquema = new GridBagLayout();
c = new GridBagConstraints();
aceptar = new JButton("Aceptar");
title = new JLabel("Agregar Nuevo Ingreso");
ingreso2 = new JLabel("Monto del Ingreso: ");
nombreingreso2 = new JLabel("Nombre del Ingreso: ");
frecuencia2 = new JLabel("Frecuencia con la cual recibe el ingreso: ");
ingreso3 = new JTextField("Escriba aqui el monto");
nombreingreso3 = new JTextField("Escriba aqui el nombre");
frecuencia3 = new JComboBox(Frecuencia);
//FASE DE ACOMODO
c.anchor = GridBagConstraints.CENTER;
addobjeto(title, 0, 0, 1, 1);
c.anchor = GridBagConstraints.LINE_START;
addobjeto(nombreingreso2 , 0, 4, 1, 1);
addobjeto(nombreingreso3, 1, 4, 1, 1);
addobjeto(ingreso2, 0, 5, 1, 1);
addobjeto(ingreso3, 1, 5, 1, 1 );
addobjeto(frecuencia2, 0 , 6, 1, 1);
addobjeto(frecuencia3, 1, 6, 1, 1);
c.anchor = GridBagConstraints.CENTER;
addobjeto(aceptar,0 ,7 ,1, 1);
contenedor.add(objcontainer);
objcontainer.setLayout(esquema);
setVisible(true);
}
}
The order in which you do things is very important. It pointless doing something like...
objcontainer = new JPanel();
esquema = new GridBagLayout();
// Add a bunch of stuff
objcontainer.setLayout(esquema);
You've basically added components to a container (which is using a FlowLayout) and then changed the layout manager. The constraints won't carry across, they are typically incompatiable between layouts (what's a FlowLayout going to do with GridBagConstraints anyway)
Instead, set the layout first
objcontainer = new JPanel();
esquema = new GridBagLayout();
objcontainer.setLayout(esquema);
// Add components.
This also holds true for when you establish a window...
public agregaringreso(){
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle("Agregar Nuevo Ingreso - EkPek");
pack();
setResizable(false);
setSize(500, 200);
setLocationRelativeTo(null);
It's all kind of pointless, as you've not actually added anything to the window, so pack can't actually do it's job (it's got nothing to pack)
Instead, build the UI first, the "set up" the window properties...
public agregaringreso(){
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle("Agregar Nuevo Ingreso - EkPek");
//FASE DE INICIALIZACION
contenedor = getContentPane();
contenedor.setBackground(Color.RED);
objcontainer = new JPanel();
esquema = new GridBagLayout();
objcontainer.setLayout(esquema);
c = new GridBagConstraints();
// Add components
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
it worked separating only by one gridy. But when I put it 2 or more away that the last object it just stays like if I put 1.
If you mean that jumping the value of gridy doesn't do anything than you're right, it's intended. The grid only consists of rows and columns which have components in them.
Example: if you have 2 components, the first at (0,0) and the second at (0,4), then the gridy values 1 through 3 are not counted. The result is that the second component is actually at (0,1). Same goes for gridx.
also the anchors dont work perfectly, besides the LINE START one, the Center ones are failing.
In your example the CENTER anchor value is functioning as intended. If the component is smaller than its available space (and it was not instructed to fill that space with fill), it will be aligned to the center of the space.
What you probably want it for the component to be in the center of the whole grid, and not in the center of its available space. To do this, you must set it so that the component spans the grid's width (or height) by setting its gridwidth appropriately.
Picture comparison
#MadProgrammer's answer already explained how to fix your setup (I will mention it below in the notes). You're supposed to get the top picture after those corrections. The red lines separate rows and the blue lines separate columns - this is your grid.
You see that the components in the first and last rows are centered in column 0 because this is their available space. In the bottom picture, they are centered in both columns since I instructed them to span 2 columns.
I also noted a space discrepancy in the top picture with a yellow rectangle. This happens because the components are not filling all their available space. While it's your choice, it is customary in such layout to do as shown in the bottom picture.
Code comparison
c.anchor = GridBagConstraints.CENTER; // Redundant - default
addobjeto(title, 0, 0, 2, 1);
c.anchor = GridBagConstraints.LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
addobjeto(nombreingreso2, 0, 1, 1, 1);
addobjeto(nombreingreso3, 1, 1, 1, 1);
addobjeto(ingreso2, 0, 2, 1, 1);
addobjeto(ingreso3, 1, 2, 1, 1);
addobjeto(frecuencia2, 0, 3, 1, 1);
addobjeto(frecuencia3, 1, 3, 1, 1);
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.NONE;
addobjeto(aceptar, 0, 4, 2, 1);
Set the gridwidth of title and aceptar to 2 (GridBagConstraints.REMAINDER will also work) to allow them to span 2 columns.
For the rest of the components, set c.fill = GridBagConstraints.HORIZONTAL; to allow them to align nicely with themselves (yellow rectangle). Remember to reset it c.fill = GridBagConstraints.NONE; for aceptar if you don't want the button to strech.
Specifying c.anchor = GridBagConstraints.CENTER; is redundant for the first component as it is the default, but it can make the code clearer.
Notes:
You don't need your JLabels to be fields as you probably don't need to hold a reference to them. Local variables will do just as well and will decrease the memory usage.
Class names should start with an uppercase (Agregaringreso).
As for my "setup" (as MadProgrammer explained): before adding the components I have
esquema = new GridBagLayout();
objcontainer = new JPanel(esquema);
c = new GridBagConstraints();
and at the end I have
getContentPane().add(objcontainer);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle("Agregar Nuevo Ingreso - EkPek");
pack();
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
(You don't need to hold a reference to the content pane.)

JScrollPane not getting larger when JLabels are added to panel

my problem is that although the scroll bar is appearing on the specific panel I want it to it's not extending as labels are added. I would like it to extend when the labels start going off the panel that they are being added to.
I have a main JPanel 'panel' which uses GridBagLayout, within that I have 5 other panels, the ones that needs a scroll bar is boardPanel which has null value for setLayout()
panel = new JPanel();
panel.setLayout(new GridBagLayout());
...
1Panel = new JPanel();
1Panel.setPreferredSize(new Dimension(480, 800));
1Panel.setLayout(null);
scrollPanel = new JScrollPanel(1Panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
...
c.weighty = 1.0;
c.weightx = 0.6;
c.gridx = 0;
c.gridy = 0;
c.gridheight = 3;
panel.add(scrollPanel, c);
...
I hope this is enough information, thank you so much for your help in advance.
Don't use a null layout!!!
Don't use setPreferredSize()!!!
Scrollbars will appear when the preferred size of the component is greater than the size of the scroll pane. By hardcoding a size you break this functionality.
Use a layout manager and the preferred size will change dynamically as you add components to the panel.
Read the Swing tutorial on Layout Managers

Java GridBagLayout + Absolute Layout

I am trying to make a 3 column layout, in each column i want to be able to absolute position labels and textboxes.
Problem is that my label (jLabel2) never even gets displayed..
Here is my code:
/**
* Top JPanel (Top)
*/
JPanel pnlTop = new JPanel();
pnlTop.setBackground(new java.awt.Color(223, 223, 217));
pnlTop.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new java.awt.Color(173, 173, 166)));
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 5; // five rows
c.gridheight = 1; // one column
c.fill = GridBagConstraints.BOTH;
//c.weighty = 0.04;
add(pnlTop, c);
/**
* Top JPanel Content (Here is where i want to put absolute content)
*/
JPanel pnlTopContent = new JPanel();
pnlTopContent.setLayout(null);
jLabel2.setFont(new java.awt.Font("Lucida Grande", 1, 16)); // NOI18N
jLabel2.setText("Hello");
jLabel2.setLocation(150, 50);
pnlTopContent.add(jLabel2);
pnlTop.add(pnlTopContent);
Any ideas what i am doing wrong?
Then its showing but not in the right place
What does "right place" mean to you? Why are you even adding you label to a second panel? Why not just add the label directly to the pnlTopContent?
GridBagLayout has a constraint that allows you to position the component right/left/center of the column. Read the section from the Swing tutorial on How to Use GridBagLayout. You might want to start with the anchor constraint.
Use layout manager for pnlTopContent. Which one is right depends on what you want. Even the default FlowLayout might work. If you want to center the label, you can for example use FlowLayout with center alignment:
pnlTopContent.setLayout(new FlowLayout(FlowLayout.CENTER));

GridBagLayout align textField?

I want to shorten my text field so it doesn't stretch to to the end of my jframe so this is how it looks now:
How do control the width of the textfield so it does't streatch like that I tried setPreferedSize() and setSize() yet they didn't work??
#Override
public void run() {
JFrame frame = new JFrame("Test Calculator");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(500, 500);
JPanel panel = new JPanel(new GridBagLayout());
frame.getContentPane().add(panel, BorderLayout.NORTH);
GridBagConstraints c = new GridBagConstraints();
JLabel testLabel = new JLabel("Enter Score For Test 1: ");
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(40, 15, 15, 0);
panel.add(testLabel , c);
JTextField txtField1 = new JTextField("TextField");
c.gridx = 1;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = .5;
panel.add(txtField1 , c);
}
You're telling the layout that the text field must fill horizontally, so that's what it does. Replace
c.fill = GridBagConstraints.HORIZONTAL;
by
c.fill = GridBagConstraints.NONE;
First and foremost, get rid of this:
frame.setSize(500, 500);
Instead let your components and layout managers size themselves by calling pack() on your JFrame after filling it and before setting it visible.
Next, consider either adding an empty border around your main container, or else adding an empty JLabel to your GridBagLayout using container.
You can also give your JTextField appropriate insets to give a cushion around it.
c.insets = new Insets(40, 15, 15, 40);
panel.add(txtField1, c);
You can change how many columns a particular component takes up by changing GridBagConstraints gridwidth field.
//this would make the next component take up 2 columns
c.gridwidth = 2;
You could have a jpanel and set its dimensions and layout, then add the elements to that panel and add the panel to your jframe.
There are different layout types that can be used depending on what you need to be done. I usually like to use Box's. They have methods that allow you to create horizontal/vertical struts, create rigid areas(this is what I usually use)
Box box1 = Box.createHorizontalBox();
Box box2 = Box.createVerticalBox();
box1.add(Box.createRigidArea(new Dimension(30,0)));
box1.add(testLabel);
box1.add(Box.createRigidArea(new Dimension(30,0)));
box1.add(txtField1);
box1.add(Box.createRigidArea(new Dimension(30,0)));
box2.add(Box.createRigidArea(new Dimension(0,30)));
box2.add(box1);
box2.add(Box.createRigidArea(new Dimension(0,30)));
JFrame.add(box2);
Check this link out for descriptions and how to use all the different kinds of layouts: http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

Set minimum height for each component in JScrollPane

Is there any method I could implement that will ensure each button within the pane maintains a minimum height? I have attempted using itembutton.setSize() method but it has no effect.
JPanel itemPanel = new JPanel();
itemPanel.setLayout(new GridLayout(0,1));
for(final Item i: list){
JButton itemButton = new JButton(i.getName());
itemPanel.add(itemButton);
}
JScrollPane itemPane = new JScrollPane(itemPanel);
itembutton.setMinimumSize(minimumSize) ?
Edit: Just found that, as this java tutorial seems to tell, there is no way to do that with GridLayout.
Each component takes all the available space within its cell, and each cell is exactly the same size
So I guess you'll have to try another layout. I can suggest (don't know if it's well suited but it works) GridBagLayout. Example with 2 buttons:
itemPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.weightx = 0.5;
itemPanel.add(new JButton("A"), c);
c.gridx = 1;
c.weightx = 0.5;
itemPanel.add(new JButton("B"), c);
Have a look to http://docs.oracle.com/javase/tutorial/uiswing/layout/index.html

Categories

Resources