About using GridBagLayout in Java - java

I'm learning how to use GridBagLayout. I created two buttons in a JFrame. I tried making it that one of them occupies one collumn (the default), and the other two collumns, thus being twice the size of the first one (I know I can acheive this using setPrefferredSize, but my intention is to learn how to use gridwidth and gridheight).
What's the problem? Thanks
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
Main(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
JPanel panel1 = new JPanel(new GridBagLayout());
JButton b1,b2;
b1 = new JButton("button 1");
b2 = new JButton("button 2");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridwidth = 1;
panel1.add(b1);
gbc.gridx = 2;
gbc.gridwidth = 2;
panel1.add(b2);
add(panel1);
setVisible(true);
}
public static void main(String[]args){
Main m = new Main();
}
}

It doesn't matter how many columns the second button's width.
Actually both buttons will be asked for their preferred width and the width will be set to them if it's enough space for them.
If it's less space then min width is used.
If there is extra space it's distributed between controls according to weights proportions.
You can try to set iPadX=100 for the first and iPadx=200 and set proportion iPadX=1 for the first and iPadx=2 for the second.

The problem is that all the columns of a GridBagLayout don't have the same width. The widths are computed based on the preferred size of the components they contain. So, you could use 3, 4 or 100 as the gridwidth for the second button, it wouldn't change anything.
You need to use fillx and weightx to change the way the buttons resize.

Try using GridBagConstraint in this way, hope this will help you.
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
Main(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
JPanel panel1 = new JPanel(new GridBagLayout());
JButton b1,b2;
b1 = new JButton("button 1");
b2 = new JButton("button 2");
panel1.add(b1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
panel1.add(b2, new GridBagConstraints(1, 0, 1, 1, 2.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
add(panel1);
setVisible(true);
}
public static void main(String[]args){
Main m = new Main();
}
}
EDIT
Or change in your code Like this below:
gbc.gridx = 1;
gbc.gridwidth = 1;
panel1.add(b1, gbc);
gbc.gridx = 2;
gbc.gridwidth = 2;
gbc.fill = gbc.HORIZONTAL; //set fill property to HORIZONTAL
gbc.weightx= 2.0;
panel1.add(b2, gbc); //While adding button also add it with gbc

Related

How to place GUI object at specific x/y place within cell within GridBagLayout

I'm new to Java Swing and am doing a small project to help me get familiar to use it. I'm trying to specify the placement dimensions of my objects (and their sizes), but I can't seem to get it right. I have the Object sizes presenting correct, but can't place them where I want. Below is an example of what it currently looks like, and what I'm looking for...
Currently...
Need to make it look like...
Below is the code I drummed up...
package Main;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import org.apache.commons.lang3.ArrayUtils;
public class StartGui extends JFrame implements ActionListener {
private static final String[] GuiCharSelDefault = {"--- Select Character ---"};
private static final int unselectedDefaultElement = 0;
private static final String[] GuiCharSel = (String[])ArrayUtils.addAll(GuiCharSelDefault, Calculator.Characters);
private String[] lvlRange = SupportMethods.createArrRange("- -", 1, 99);
/*
* Interactive GUI Objects
*/
JLabel charPic;
JComboBox charSelCombo = new JComboBox(GuiCharSel);
JComboBox pickLvlAns = new JComboBox(lvlRange);
JLabel nextLvlAns = new JLabel("- -");
public StartGui() {
/*
* Non-Interactive GUI Objects
*/
JPanel topFrame = new JPanel();
JPanel bottomFrame = new JPanel();
JPanel selPane = new JPanel();
JLabel pickLvl = new JLabel("Pick Current Level:");
JLabel nextLvl = new JLabel("Next Level:");
//*******************************************************************************
/*
* Top Frame Settings
*/
TitledBorder topFrameTitle;
Border blackLine = BorderFactory.createLineBorder(Color.black);
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compound = BorderFactory.createCompoundBorder(raisedBevel, loweredBevel);
topFrameTitle = BorderFactory.createTitledBorder(compound, "Character");
topFrameTitle.setTitleJustification(TitledBorder.CENTER);
topFrame.setBorder(topFrameTitle);
topFrame.setLayout(new BoxLayout(topFrame, BoxLayout.X_AXIS));
/*
* Adds Character Picture
*/
charPic = new JLabel("", null, JLabel.CENTER);
charPic.setPreferredSize(new Dimension(100,100));
topFrame.add(charPic);
//*******************************************************************************
/*
* Selection Pane Settings
*/
selPane.setLayout(new GridBagLayout());
selPane.setBorder(blackLine);
/*
* Adds Character Selection ComboBox
*/
charSelCombo.setPrototypeDisplayValue(charSelCombo.getItemAt(unselectedDefaultElement));
selPane.add(charSelCombo, setGbc(0,0, "WEST", 0, 1, setInsets(0, 10, 0, 0)));
/*
* Adds "Pick Current Level:" Label
*/
selPane.add(pickLvl, setGbc(0,1, "EAST", 0, 1, setInsets(0, 0, 0, 0)));
/*
* Adds "Next Level:" Label
*/
selPane.add(nextLvl, setGbc(0,2, "EAST", 0, 1, setInsets(0, 0, 0, 0)));
/*
* Adds Character Current Level ComboBox
*/
pickLvlAns.setPrototypeDisplayValue(pickLvlAns.getItemAt(lvlRange.length - 1));
selPane.add(pickLvlAns, setGbc(1,1, "WEST", 1, 1, setInsets(0, 10, 0, 0)));
/*
* Adds Character Next Level Label
*/
selPane.add(nextLvlAns, setGbc(1,2, "WEST", 1, 1, setInsets(0, 23, 0, 0)));
//*******************************************************************************
/*
* BOTTOM PANE
*/
TitledBorder bottomFrameTitle;
bottomFrameTitle = BorderFactory.createTitledBorder(compound, "Stats");
bottomFrameTitle.setTitleJustification(TitledBorder.CENTER);
bottomFrame.setBorder(bottomFrameTitle);
//*******************************************************************************
/*
* Display everything in GUI to user
*/
add(topFrame, BorderLayout.NORTH);
add(bottomFrame,BorderLayout.CENTER);
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent arg0) {
String charName = ((JComboBox)(arg0.getSource())).getSelectedItem().toString();
String image = "../images/"+charName+".png";
charPic.setIcon(new ImageIcon(new javax.swing.ImageIcon(getClass().getResource(image)).getImage().getScaledInstance(100, 100, Image.SCALE_SMOOTH)));
charSelCombo.removeItem(GuiCharSel[unselectedDefaultElement]);
pickLvlAns.removeItem(lvlRange[unselectedDefaultElement]);
}
private GridBagConstraints setGbc(int gridx, int gridy, String anchorLocation, double weightx, double weighty, Insets insets){
GridBagConstraints gbc = new GridBagConstraints();
if (anchorLocation.toUpperCase().equals("NORTHWEST")){
gbc.anchor = GridBagConstraints.NORTHWEST;
} else if (anchorLocation.toUpperCase().equals("NORTH")){
gbc.anchor = GridBagConstraints.NORTH;
} else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
gbc.anchor = GridBagConstraints.NORTHEAST;
} else if (anchorLocation.toUpperCase().equals("WEST")){
gbc.anchor = GridBagConstraints.WEST;
} else if (anchorLocation.toUpperCase().equals("EAST")){
gbc.anchor = GridBagConstraints.EAST;
} else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
gbc.anchor = GridBagConstraints.SOUTHWEST;
} else if (anchorLocation.toUpperCase().equals("SOUTH")){
gbc.anchor = GridBagConstraints.SOUTH;
} else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
gbc.anchor = GridBagConstraints.SOUTHEAST;
} else {
gbc.anchor = GridBagConstraints.CENTER;
}
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.weightx = weightx;
gbc.weighty = weighty;
gbc.insets = insets;
return gbc;
}
private Insets setInsets(int top, int left, int bottom, int right){
Insets insets = new Insets(top,left,bottom,right);
return insets;
}
public static void main(String[] args) {
new StartGui();
}
}
If anyone could tell me if there is a way to do this, it would really help a alot
Edit: With the help from MadProgrammer, I did some tweaking to the code above which actually made it work.
weightx and weighty determine how much of the left over space is supplied to the given column/row. If you supply a weightx/y value to two or more columns/rows, the space is divided between them, so, setting the weightx of column 1 and 2, like you have, means that they share 50% of the left of space, which is why it's looking the way it is.
Instead, only the last column really needs to have a weightx value at all
selPane.setLayout(new GridBagLayout());
selPane.setBorder(blackLine);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(2, 2, 2, 2);
charSelCombo.setPrototypeDisplayValue("Hello");
selPane.add(charSelCombo, gbc);
gbc.gridy++;
selPane.add(pickLvl, gbc);
gbc.gridy++;
selPane.add(nextLvl, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 1;
selPane.add(pickLvlAns, gbc);
gbc.gridy++;
selPane.add(nextLvlAns, gbc);
I simplified the code a little (for me). One of the nice things about GridBagConstraints is, GridBagLayout will make a copy of the constraints you supply, so you can share it among multiple components, like I have above, it makes it easier to update and modify, as you maintain the overall relationship between the components

GridBagLayout erratic resizing and displaying

I'm making a program that uses a GridBagLayout in a container. My primary use for this is to have two JPanels, which occupy 75% and 25% of the horizontal space of the window. For some reason though, the two panels look more like 90/10, and when resizing, the smaller one rapidly changes in size, between it's apparent minimum size, and what I believe is the desired 25%.
Here is the relevant code.
frmReedreadV = new JFrame();
frmReedreadV.setBounds(x, y, width, height);
frmReedreadV.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmReedreadV.getContentPane().setLayout(new BoxLayout(frmReedreadV.getContentPane(), BoxLayout.Y_AXIS));
JPanel stretchyPanel = new JPanel();
frmReedreadV.getContentPane().add(stretchyPanel);
stretchyPanel.setLayout(new CardLayout(0, 0));
JPanel textAndUsers = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 1;
textArea = new JTextArea();
textArea.setMargin(new Insets(2, 5, 5, 2));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
scrollPane = new JScrollPane(textArea);
scrollPane.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
gbc.weightx = 0.8;
textAndUsers.add(scrollPane, gbc);
list = new FriendsList(listUpdate);
gbc.weightx = 0.2;
textAndUsers.add(list.frmUserList, gbc);
stretchyPanel.add(textAndUsers);
FriendsList is a JList contained in a JPanel.
There are other buttons and text fields in the main CardLayout content pane, but those shouldn't affect what is inside of this GridBagLayout, correct?
I made another copy of this JPanel as a standalone application, and it displays and resizes perfectly. See here:
JFrame frame = new JFrame();
frame.getContentPane().setLayout((new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 550, 600);
JPanel stretchyPane = new JPanel();
frame.getContentPane().add(stretchyPane);
stretchyPane.setLayout(new CardLayout(0, 0));
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JTextArea text = new JTextArea();
text.setMargin(new Insets(2, 5, 5, 2));
JScrollPane panel1 = new JScrollPane(text);
FriendsList panel2 = new FriendsList(new Object());
c.fill = GridBagConstraints.BOTH;
c.weightx = .8;
c.weighty = 1;
panel.add(panel1, c);
c.weightx = .2;
//c.fill = GridBagConstraints.HORIZONTAL;
panel.add(panel2.frmUserList, c);
stretchyPane.add(panel);
frame.setVisible(true);
What could be causing the difference between the two, since I've replicated my original line by line into the copy?
The weightx and weighty properties might appear to act as proportional sizes, but that is not what they do. In fact they determine the distribution of extra space in the layout.
If you set everything to its preferred size by calling pack() on your JFrame, there will be no extra space. Which means the weightx and weighty properties have no effect while it's in that state.
Once the user starts resizing the window to be larger, there will be extra space, and only then will GridBagLayout consult the weightx and weighty properties to determine how to apportion that extra space to each column and row. Until then, it's entirely possible for a component with a small weightx to be wider than a component with a larger weightx, if their preferred sizes dictate it.
Hopefully this simple program will demonstrate this concept. Try using the mouse (or keyboard) to resize the window to be wider, and observe how each of the textfields grows:
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GridBagProportions {
static void buildAndShowWindow() {
JTextField small = new JTextField("small (0.8)", 5);
JTextField large = new JTextField("LARGE (0.2)", 30);
small.setMinimumSize(small.getPreferredSize());
large.setMinimumSize(large.getPreferredSize());
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets.left = 6;
gbc.insets.top = 6;
gbc.insets.bottom = 6;
gbc.weightx = 0.8;
panel.add(small, gbc);
gbc.weightx = 0.2;
gbc.insets.right = 6;
panel.add(large, gbc);
JFrame frame = new JFrame("GridBagLayout Proportions");
frame.getContentPane().add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
buildAndShowWindow();
}
});
}
}
So what can be done about it? Well, this is one layout scenario that GridBagLayout cannot do. I would try using a SpringLayout:
SpringLayout layout = new SpringLayout();
JPanel textAndUsers = new JPanel(layout);
SpringLayout.Constraints scrollPaneConstraints =
new SpringLayout.Constraints(scrollPane);
Spring scrollPaneWidth = scrollPaneConstraints.getWidth();
SpringLayout.Constraints listConstraints =
new SpringLayout.Constraints(scrollPaneWidth,
scrollPaneConstraints.getY(),
Spring.scale(scrollPaneWidth, 0.25f),
scrollPaneConstraints.getHeight());
layout.putConstraint(SpringLayout.EAST, textAndUsers, 0,
SpringLayout.EAST, frmUserList);
layout.putConstraint(SpringLayout.SOUTH, textAndUsers, 0,
SpringLayout.SOUTH, scrollPane);
textAndUsers.add(scrollPane, scrollPaneConstraints);
textAndUsers.add(frmUserList, listConstraints);
Notice that the creation of listConstraints specifies a width argument which is Spring.scale(scrollPaneWidth, 0.25f). This ensures the list is always one-fourth as wide as the scrollPane containing the JTextArea.
SpringLayout is tricky to use, in that you have to make sure to link the far edges of the layout container to child components explicitly, because SpringLayout won't grow to accommodate all the child components automatically. That's what the putConstraint calls are doing.

Java : divide the screen

I try to do a simple swing window, but with the layout it's not easy...
I mean I just want a window with 3 panels :
header with 20% of window in height
content with 60% of window in height
footer with 20% of window in height
But I can't succeed to have what I want. I used a gridLayout(3,1) but I can't specify the height.
public class Window extends JFrame implements Serializable {
private JPanel _header;
private JPanel _content;
private JPanel _footer;
public Window() {
GridLayout grid = new GridLayout(3,1);
setLayout(grid);
_header = new JPanel();
_header.setBackground(Color.GRAY);
getContentPane().add(_header);
_content = new JPanel();
JScrollPane jsp = new JScrollPane(_content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
getContentPane().add(jsp);
_footer = new JPanel();
_footer.setBackground(Color.GRAY);
getContentPane().add(_footer);
pack();
validate();
setTitle("Chat client");
setVisible(true);
setSize(500, 500);
setLocationRelativeTo(null);
}
Can you help me ?
Best regards
GridBagLayout is capable of dividing vertical or horizontal space proportionally.
Here's an example that displays a red JPanel in the top 20% of a window, a green JPanel in the middle 60%, and a blue JPanel in the bottom 20%:
JFrame window = new JFrame();
window.setLayout(new GridBagLayout());
JPanel top = new JPanel(), middle = new JPanel(), bottom = new JPanel();
top.setBackground(Color.red);
middle.setBackground(Color.green);
bottom.setBackground(Color.blue);
GridBagConstraints c = new GridBagConstraints();
// we want the layout to stretch the components in both directions
c.fill = GridBagConstraints.BOTH;
// if the total X weight is 0, then it won't stretch horizontally.
// It doesn't matter what the weight actually is, as long as it's not 0,
// because the grid is only one component wide
c.weightx = 1;
// Vertical space is divided in proportion to the Y weights of the components
c.weighty = 0.2;
c.gridy = 0;
window.add(top, c);
// It's fine to reuse the constraints object; add makes a copy.
c.weighty = 0.6;
c.gridy = 1;
window.add(middle, c);
c.weighty = 0.2;
c.gridy = 2;
window.add(bottom, c);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
Result:
GridLayout always spaces evenly. You could instead use GridBagLayout, the most evil of all the Java layout managers. I've given them "weights" of 20, 60, 20 so you can see which values are which. You can just as easily use 2, 6, 2, it doesn't matter it's just a ratio. Look at the GridBagLayout tutorial for more info.
Example
public class Window extends JFrame implements Serializable {
private JPanel _header;
private JPanel _content;
private JPanel _footer;
public Window() {
GridBagLayout grid = new GridBagLayout();
setLayout(grid);
_header = new JPanel();
_header.setBackground(Color.GRAY);
// <=== add with constraints here
getContentPane().add(_header, new GridBagConstraints(0, 0, 1, 1, 1, 20, GridBagConstraints.BASELINE, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
_content = new JPanel();
JScrollPane jsp = new JScrollPane(_content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
// <=== add with constraints here
getContentPane().add(jsp, new GridBagConstraints(0, 1, 1, 1, 1, 60, GridBagConstraints.BASELINE, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
_footer = new JPanel();
_footer.setBackground(Color.GRAY);
// <=== add with constraints here
getContentPane().add(_footer, new GridBagConstraints(0, 2, 1, 1, 1, 20, GridBagConstraints.BASELINE, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
pack();
validate();
setTitle("Chat client");
setVisible(true);
setSize(500, 500);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Window();
}
});
}
}
Screenshot

GridBagLayout is not working

this.rootComponent.setLayout(new GridBagLayout());
GridBagConstraints gbc=new GridBagConstraints();
//gbc.gridwidth=2;
gbc.gridx=0;
gbc.gridy=0;
gbc.gridwidth=8;
gbc.anchor=GridBagConstraints.FIRST_LINE_START;
this.rootComponent.add(new JLabel("Test label 1"),gbc);
gbc.gridx=8;
gbc.gridy=12;
gbc.gridwidth=GridBagConstraints.REMAINDER;
gbc.anchor=GridBagConstraints.FIRST_LINE_START;
this.rootComponent.add(new JLabel("Test label"),gbc);
Want to format it like this. grey part shows the jpanel part. Initially i want to layout the first 2 jpanel correctly . which is not working. how to fix it?
You are failing to specify any weightx and weighty values to the GridBagConstraints. Moreover your gridwidth values are wrong, since it only needs to be 2 for the bottom most JPanel, for the rest it needs to be 1.
Explanation of what I am doing :
Consider JPanels BLUE and RED, they are to be placed along the X-AXIS, in the ratio
70:30, with respect to each other (therefore their weightx will be 0.7 and 0.3 respectively. Since the total area along the X-AXIS is 1.0).
Now both of these BLUE and RED JPanels are to be placed along the Y-AXIS, with respect to the third GREEN JPanel in the ratio 90:10, therefore, both of these BLUE and RED will have weighty = 0.9, and the GREEN JPanel will have weighty = 0.1, but since GREEN JPanel is suppose to occupy the whole area (with respect to X-AXIS), as occupied by BLUE and RED JPanels, for that matter, its gridwidth = 2 and weightx = 1.0.
Try this code example :
import java.awt.*;
import javax.swing.*;
public class GridBagLayoutExample
{
private GridBagConstraints gbc;
public GridBagLayoutExample()
{
gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
}
private void displayGUI()
{
JFrame frame = new JFrame("GridBagLayout Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = getPanel(Color.WHITE);
contentPane.setLayout(new GridBagLayout());
JPanel leftPanel = getPanel(Color.BLUE);
JPanel rightPanel = getPanel(Color.RED);
JPanel bottomPanel = getPanel(Color.GREEN.darker());
addComp(contentPane, leftPanel
, 0, 0, 0.7, 0.9, 1, 1, GridBagConstraints.BOTH);
addComp(contentPane, rightPanel
, 1, 0, 0.3, 0.9, 1, 1, GridBagConstraints.BOTH);
addComp(contentPane, bottomPanel
, 0, 1, 1.0, 0.1, 2, 1, GridBagConstraints.BOTH);
frame.setContentPane(contentPane);
//frame.pack();
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void addComp(JPanel panel, JComponent comp
, int gridX, int gridY
, double weightX, double weightY
, int gridWidth, int gridHeight, int fill)
{
gbc.gridx = gridX;
gbc.gridy = gridY;
gbc.weightx = weightX;
gbc.weighty = weightY;
gbc.gridwidth = gridWidth;
gbc.gridheight = gridHeight;
gbc.fill = fill;
panel.add(comp, gbc);
}
private JPanel getPanel(Color backColour)
{
JPanel panel = new JPanel();
panel.setOpaque(true);
panel.setBackground(backColour);
panel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
return panel;
}
public static void main(String[] args)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
new GridBagLayoutExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
Here is the OUTPUT of the same :

Java-Swing: A problem using layout managers!

I'm working on a JDialog (by hand, no GUI builders) and I'm having a problem doing the layout.
I have this:
My problem is that I don't know what how to tell that JList (within a JScrollPane) to have a Maximum width, I used the setSize, setMaximumSize and nothing works! I need that JList's width to be the half of the picture's size.
Explain the layouts:
The "Gene Information" is a GridLayout 2x4, it's contained by a JPanel with BoxLayout, the +/- JButtons is a BoxLayout also, all what I said before is within a BoxLayout.
Now, the "Genes" JPanel is a GridBagLayout.
What can I do?
Thanks in advance!
PD: The other borders are just for seeign the boundaries of the components.
Source Code:
scpGenesList.setViewportView(lstGenesList);
pnlGeneInfo.setLayout(new GridLayout(4, 2, 10, 10));
pnlGeneInfo.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Gene Information"),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
lblGeneSymbol.setText("Symbol:");
lblGeneSymbol.setHorizontalAlignment(SwingConstants.RIGHT);
lblGeneChromosome.setText("Chromosome:");
lblGeneChromosome.setHorizontalAlignment(SwingConstants.RIGHT);
lblGeneStartPosition.setText("Start Position:");
lblGeneStartPosition.setHorizontalAlignment(SwingConstants.RIGHT);
lblGeneStopPosition.setText("Stop Position:");
lblGeneStopPosition.setHorizontalAlignment(SwingConstants.RIGHT);
pnlGeneInfo.add(lblGeneSymbol);
pnlGeneInfo.add(lblGeneSymbolValue);
pnlGeneInfo.add(lblGeneChromosome);
pnlGeneInfo.add(lblGeneChromosomeValue);
pnlGeneInfo.add(lblGeneStartPosition);
pnlGeneInfo.add(lblGeneStartPositionValue);
pnlGeneInfo.add(lblGeneStopPosition);
pnlGeneInfo.add(lblGeneStopPositionValue);
pnlGWASAddRemoveButtons.setLayout(new BoxLayout(pnlGWASAddRemoveButtons, BoxLayout.X_AXIS));
pnlGWASAddRemoveButtons.add(Box.createHorizontalGlue());
pnlGWASAddRemoveButtons.add(cmdGenesAdd);
pnlGWASAddRemoveButtons.add(Box.createHorizontalStrut(10));
pnlGWASAddRemoveButtons.add(cmdGenesRemove);
pnlGWASAddRemoveButtons.add(Box.createHorizontalGlue());
pnlGeneInfoButtons.setLayout(new BoxLayout(pnlGeneInfoButtons, BoxLayout.Y_AXIS));
pnlGeneInfoButtons.add(pnlGeneInfo);
pnlGeneInfoButtons.add(Box.createVerticalStrut(10));
pnlGeneInfoButtons.add(pnlGWASAddRemoveButtons);
pnlGenesPanel.setLayout(new GridBagLayout());
pnlGenesPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Genes"),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
GridBagConstraints ctrGenes = new GridBagConstraints();
ctrGenes.fill = GridBagConstraints.BOTH;
ctrGenes.gridx = 0;
ctrGenes.gridy = 0;
ctrGenes.gridwidth = 1;
ctrGenes.gridheight = 1;
ctrGenes.weighty = 1.0;
ctrGenes.weightx = 1.0;
ctrGenes.insets = new Insets(0, 0, 0, 10);
pnlGenesPanel.add(scpGenesList, ctrGenes);
GridBagConstraints ctrGenesInfoButton = new GridBagConstraints();
ctrGenesInfoButton.fill = GridBagConstraints.BOTH;
ctrGenesInfoButton.gridx = 1;
ctrGenesInfoButton.gridy = 0;
ctrGenesInfoButton.gridwidth = 1;
ctrGenesInfoButton.gridheight = 1;
ctrGenesInfoButton.weighty = 1.0;
ctrGenesInfoButton.weightx = 1.0;
pnlGenesPanel.add(pnlGeneInfoButtons, ctrGenesInfoButton);
contentPane.add(pnlGenesPanel);
pack();
Why not give the "Genes" panel a 2x1 GridLayout? That should ensure that both sides have the same size.
But actually, it would make more sense to me to give the list all space not taken by the controls, since those require a fixed amount of space while the list may benefit from all additional space it can get, if there are wide entries.
To that end, I would give the "Genes" panel a BorderLayout, put the list in the CENTER slot and the controls in the EAST slot.
Following #Michael Borgwardt's suggestion to let the list grow, you can use setVisibleRowCount() to produce a convenient initial panel size. If necessary, you can also examine the Dimension returned by getPreferredScrollableViewportSize(), which "computes the size of viewport needed to display visibleRowCount rows."
Without seeing all the code here it may be impossible to tell you what is wrong. One thing I would suggest if you have time is to take a look at MigLayout. You can use it with Swing & SWT and once you learn it is a pretty powerful layout manager IMHO.
Hope this helps, good luck.
It doesn't answer your question - but I've found that the JGoodies FormLayout to be more intuitive than the GridBagLayout. The library, as well as some examples, can be found here:
http://jgoodies.com/freeware/forms/index.html
I think the earlier solutions are all valid, and it is more of a coding preference in terms of which layout managers to use. Based on your requirement, here is a working one with standard layout managers only (Grid, GridBag and Border). Have fun, - MS.
import java.awt.;
import javax.swing.;
import javax.swing.border.*;
public class GeneDialog extends JDialog {
private String[] plusMinus = {"+","-"}, tfNames = {
"Symbol", "Chromosome", "Start position", "Stop position"},
listData = {"Gene01", "Gene02", "Gene03", "Gene04", "Gene05", "Gene06",
"Gene07", "Gene08", "Gene09", "Gene10", "Gene11", "Gene12"};
private JTextField[] gtField= new JTextField[tfNames.length];
private JList list = new JList (new DefaultListModel());
public GeneDialog (Frame f, String title) {
super (f, title, true);
Container cp = getContentPane();
cp.setLayout (new GridLayout(1,2));
JScrollPane listScrollPane = new JScrollPane (list);
listScrollPane.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Genes"),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
DefaultListModel lm = (DefaultListModel) list.getModel();
for (int k = 0 ; k < listData.length ; k++)
lm.addElement (listData[k]);
cp.add (listScrollPane);
cp.add (controlPanel());
pack();
}
private GridBagConstraints makeGBC (int inset) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets (inset, inset, inset, inset);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = GridBagConstraints.RELATIVE;
return gbc;
}
private JPanel controlPanel() {
JPanel cp = new JPanel (new BorderLayout()),
bp = new JPanel (new GridBagLayout()),
tp = new JPanel (new GridBagLayout());
GridBagConstraints gbc = makeGBC (10);
for (int i = 0 ; i < tfNames.length ; i++) {
JLabel label = new JLabel (tfNames[i], JLabel.TRAILING);
tp.add (label, gbc);
}
gbc.gridx++; gbc.weightx = 1.0f;
for (int i = 0 ; i < tfNames.length ; i++) {
gtField[i] = new JTextField(12);
tp.add (gtField[i], gbc);
}
gbc = makeGBC (10);
for (int i = 0 ; i < plusMinus.length ; i++) {
JButton b = new JButton (plusMinus[i]);
bp.add (b, gbc);
gbc.gridx++;
}
cp.add (tp, "Center");
cp.add (bp, "South");
return cp;
}
public static void main (String[] args) {
new GeneDialog (null, "Genes").setVisible (true);
}}
Try setting the maximum width for both the JScrollPane and the JList that is within it.
I just want to tell that I share the same opinion as javamonkey79. Take a look at MigLayout, you'll love it, and from Java 7 on it will be standart java-onboard layout.

Categories