Nested JPanel with GridBagLayout - java

I have a JFrame with GridBagLayout. weightx and weighty values are assigned different no-zero values and GridBagConstraints.fill = GridBagConstraints.BOTH. I nested a JPanel in one of the cells and gave it a GridBagLayout too. When adding components to the nested JPanel, the cell size where the nested JPanel resides grows on all sides missing up the parent's layout. Insets and padding are not used. How can I fix this problem?Thanks.
This is an example of the GridBagConstraints values:
GridBagConstraints treePanCon = new GridBagConstraints();
treePan.setLayout(treePanGridbag);
treePanCon.fill = GridBagConstraints.BOTH;
treePanCon.weightx = 0.5;
treePanCon.weighty = 1;
treePanCon.gridx = 0;
treePanCon.gridy = 0;
treePanCon.gridwidth = 1;
treePanCon.gridheight = 1;
This is a screenshot before adding components to the nested JPanel:
This a screenshot after adding components to the nested JPanel:

That's exactly what is supposed to happen. Please explain the behavior you're looking for. As an aside the layout managers available with J2SE are less than ideal. Having done a large amount of Swing work in a past life I would highly recommend checking out JGoodies forms: http://www.jgoodies.com/freeware/forms/. Check out the whitepaper, it's easy to use and much more intuitive than GridBag.

This is probably of absolutely no use to you at this late date, but...
It looks like you probably used BOTH when laying out the two new buttons.
If the preferredSize.width on the tree is the width you want for the inner panel,
and you wanted the two new buttons to each be half the width of the tree,
set their preferredSize.width to half the preferredSize.width of the tree, and use NONE on the two buttons.
Use VERTICAL on the tree in the inner panel.
Use VERTICAL on the inner panel in the outer panel.

Related

Placing GridLayout JPanels onto a GridBagLayout JFrame

I'm trying to place two JPanels onto a JFrame using GridBagLayout.
The first JPanel uses gridLayout to create 35 columns and 27 rows of JButtons, and should have a width of 3/4 of the JFrame. This panel needs to fill the vertical space available to it.
The second JPanel also uses gridLayout and should fill the last 1/4 of the main JFrame.
Unfortunately, my first JPanel (sPan) isn't even fitting properly on the screen, and is forcing the whole second JPanel (cPan) off of the screen. How can I constrain these values to take up only their allowed proportion on the screen without them moving each other around?
If I use a blank JPanel with a background colour with my code, everything works out perfectly fine:
[1]
However, when I use my JPanel consisting of JButtons, the proportions get completely messed up:
[2]
I speculate that when I instantiate my sPan object, it's sizing each button to accommodate the size of the whole JFrame. Then when I instantiate the cPan object and try to place it next to the sPan object, the buttons aren't resizing themselves to accommodate the additional panel in the main JFrame. Does anybody know how I can fix this?
I have to use GridBagLayout for this assignment, so using normal gridLayout isn't an option.
Any tips regarding what's happening would be appreciated.
Could you simply deal with two columns? The first one taking 5/6 of the available width and the second one taking the 1/6th remaining?
You could try the following:
final JPanel sPan = new JPanel();
sPan.setBackground(Color.RED);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 5 / 6f; // change this value...
constraints.weighty = 1.00;
add(sPan, constraints);
final JPanel cPan = new JPanel();
cPan.setBackground(Color.BLUE);
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1 / 6f; // ... and this one.
constraints.weighty = 1.00;
add(cPan, constraints);
Please note: I replaced your JPanels by some empty JPanels with a background color, so even like this you can see what's going on.

Java JPanel subclass ignores bounds on adding components

I have a subclass of JPanel that I'm trying to add labels to
for(int i = 0; i < 10; i++)
{
JLabel lblPID = new JLabel("" + i);
lblPID.setBounds(55, i * 50, 15, 15);
this.add(lblPID);
}
But when this runs, the labels line up horizontally next to each other at the same y point, ignoring the bounds I'm setting. How do I have the panel lay them out vertically the way they're supposed to appear?
The likely problem is, the container you are adding your label to is using a layout manager, which is making it's own decisions about how your label should be laid out.
You should avoid using setBounds as you can not guarantee that the label will be rendered the same on different computers, even if they are running the same OS. Instead you should make use of appropriate layout managers, which make these decisions for you.
Take a look at Laying out Components within a Container for more details

GridBagLayout one cell alignment for label

I have for example 3x3 components in grid layout, and I would like all of them to be labels, but since I have some padding I want my labels to be in center of their cell. But I can't seem to manage it...
Part of the relevant code:
panel = new JPanel();
GridBagLayout gridBag = new GridBagLayout();
panel.setLayout(gridBag);
panel.setSize(new Dimension(30, 400));
GridBagConstraints c = new GridBagConstraints()
JLabel lab = new JLabel("proba");
lab.setBorder(outline);
c.fill = GridBagConstraints.BOTH;
c.gridx =2; c.gridy=2; c.ipady = 10; c.ipadx=10;
c.ipadx=100; panel.add(lab,c);
[update]
You really should post an SSCCE so we can all try it and not have to guess where the problem is. My last guess - and this is something you should do regardless of whether it fixes your current problem - is
label.setHorizontalAlignment(JLabel.CENTER);
If your label is centered and fills the entire grid cell, the text will still be left justified by default. The above change will cause the text to be centered within the label.
However if your label is not filling the cell, this won't help.
[original]
It's hard to say exactly what's wrong since this is not a full program, but here are a few comments that might get you on the right track.
First, you should be using setPreferredSize instead of setSize (see Java: Difference between the setPreferredSize() and setSize() methods in components)
When you make this change you will see that the panel is not quite what you want. It's very tall and thin. Perhaps a typo - did you mean (300,400) instead of (30,400)
Now I'm guessing all your labels will be clumped together. In order to get them to spread out you need to add:
c.weightx = .5;
c.weighty = .5;
(actually any non-zero value will work). This is described in http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
Unless you specify at least one non-zero value for weightx or weighty, all the components clump together in the center of their container. This is because when the weight is 0.0 (the default), the GridBagLayout puts any extra space between its grid of cells and the edges of the container.
This should get you close(r) ...

Why will BoxLayout not allow me to change the width of a JButton but let me change the height?

I'm trying to get the Layout of a JDialog of mine to fit a particular look that a program in which I'm porting to Java has, I've used several LayoutManagers before with great success yet for some reason I cannot seem to get this working at all. My goal is to have the Right (East) side of the JDialog contain a "Find Next" and "Cancel" button in a top-down order and then any extra space below so that the two buttons are always at the top of the JDialog, yet for some reason BoxLayout is continously ignoring any attempts at changing (this is where I'm lost) the width of a JButton. Code follows.
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),
(int)cancel.getPreferredSize().getHeight()));
JPanel example = new JPanel();
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
example.add(cancel);
example.add(Box.createGlue());
No matter what I try, cancel always retains it's normal size. I've tried setMinimumSize() and setMaximumSize() with the same parameters as setPreferredSize with no luck. I've even tried cancel.setPreferredSize(new Dimension(500, 500)); and the buttons height was the only thing adjusted, it STILL retained the default width it was given.
To clear up any questions, here is what it looks like (now that I've finished it) and you'll see that the "Find Next" and "Cancel" buttons are not the same size.
I know this is an old question but I don't really see a good explanation. So for the sake of searchers that stumble upon this I will add my two cents.
There are three methods associated with sizing components in Swing: setPreferredSize(), setMinimumSize(), and setMaximumSize(). However, the important point is that it is up to the particular layout manager being used as to whether or not it honors any of these methods.
For BoxLayout (the layout the original poster is using):
setMinimumSize() -- BoxLayout honors this
setMaximumSize() -- BoxLayout honors this
setPreferredSize() -- if X_AXIS is being used width is honored, if Y_AXIS is being used height is honored
The OP is using a Y_AXIS BoxLayout which is why only his height was being changed.
Update: I put together a page with this same information for all of the layout managers. Hopefully it can help some searchers out: http://thebadprogrammer.com/swing-layout-manager-sizing/
You may not want Box.createGlue(), which "grows as necessary to absorb any extra space in its container." Instead, use Box.createVerticalStrut() between the buttons, as shown below and in the ControlPanel of this simulation.
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);
Addendum:
adding in setMaximumSize() made it work.
This is the expected behavior for components having identical maximum widths in a vertical BoxLayout, as described in Box Layout Features. The preferred width of the container becomes that of the (equally wide) children, and the X alignment becomes irrelevant.
example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);
As mentioned in the comments on the question, you were able to fix it by switching to setMaximumSize(). However, as you noted, setPreferredSize() doesn't work. So, what's up with that?
With many things Swing, the properties used to determine the actual component size when using the BoxLayout are somewhat random (in my opinion). When determining how to render the components, Swing calls layoutComponent() on the layout manager, which is figures out where to position everything.
BoxLayout's implementation of layoutComponent() involves a call to a method that creates SizeRequirements objects for the width and height of each of the components you add to the JPanel, based on their getMinimum/Preferred/MaximumSize() methods.
Later, it calls SizeRequirements.calculateAlignedPositions() for determining the correct width values for each component, because your orientation is BoxLayout.Y_AXIS (The heights are calculated using a different method). Taking snippets from the source, the relevant implementation of this method is as follows:
for (int i = 0; i < children.length; i++) {
SizeRequirements req = children[i];
//...
int maxAscent = (int)(req.maximum * alignment);
int maxDescent = req.maximum - maxAscent;
//...
int descent = Math.min(totalDescent, maxDescent);
//...
spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}
Note that totalDescent is the available width, so descent is always set to maxDescent, which is based on SizeRequirements.maximum, which was taken from JButton.getMaximumSize(). The value of spans[i] is then used later in a call to JButton.setBounds() as the width. As you'll note, getPreferredSize() was never involved here, which is why setting it has no impact in this case.
Usually if want to ensure a size of the component in Swing you need to call setMinimumSize(), setMaximumSize(), and SetPrefferedSize() with the same value.
button.setMaximumSize(getMaximumSize());
If you put your buttons in a GridLayout panel they will be the same width.

Using Java and its SWING library

I am trying to code a very simple form using java but i am running into more trouble than i expected because of the way swing lays out components, I have tried various different layout managers and still cannot layout the form the way i would like.
Here is how i would like the form to look: link text
Does anyone have any ideas about how to go about this because im stumped?
Thanks.
The easiest for your purposes is the GridLayout. As Aaron said, Netbeans has a great GUI builder if you don't want to learn the layout managers.
Take a look at Table Layout. It is much easier to use than nearly all of the default layout managers. Your form would be very simple to construct with it.
Short of using gridbaglayout, it is doable by borderlayout, gridlayout and flowlayout. Start by breaking the form into big visual pieces and make sub layouts under top level ones.
For example, in this case I would do this:
Divide the form in two vertical pieces by gridlayout (or borderlayout); top (or central) part for the labels and textfields, bottom (or south) for the button.
In top part, make either flowlayout with center align or another gridlayout to arrange the labels and textfields.
In the bottom part, use flowlayout with center align for the button.
I have worked with Java swing for 4 years and it was a hurdle to design layouts at first, but it gets easier the more you practise.
GridBagLayout can be daunting at first, but it's very flexible, and is worth getting to know.
JButton button = ...;
JLabel[] labels = new JLabel[] {
new JLabel("Label 1"),
...
};
JTextField[] fields = new JTextField[] {
new JTextField(15),
...
};
JPanel[] rows = new JPanel[] {
new JPanel(),
...
}
Container container = getContentPane();
container.setLayout(new GridBagLayout());
GridBagConstraints cons = new GridBagConstraints();
// Layout each row's contents(label + text field)
cons.fill = GridBagConstraints.BOTH;
cons.insets = new Insets(2, 8, 2, 8);
for (int i = 0; i < rows.length; ++i) {
rows[i].setLayout(new GridBagLayout());
// Labels get 30% of the row's extra horizontal space.
cons.weightx = 0.3;
rows[i].add(labels[i], cons);
// Text fields gets 70% of the row's extra horizontal space.
cons.weightx = 0.7;
rows[i].add(fields[i], cons);
// Add each row to the panel, top to bottom
// Each row takes up all of the horizontal space.
cons.gridx = 0;
cons.weightx = 1;
container.add(rows[i], cons);
cons.gridx = GridBagConstraints.RELATIVE;
}
// Add the button at the bottom.
// Dont let button get any extra horizontal space (so it won't stretch)
cons.gridx = 0;
cons.weightx = 0;
cons.fill = GridBagConstraints.NONE;
container.add(button, cons);
By far the easiest to use layout manager I've tried, at least for doing something similar to that, is DesignGridLayout. With that, the code would look something like:
layout.row().grid(new JLabel("JLabel1")).add(new JTextField());
layout.row().grid(new JLabel("JLabel2")).add(new JTextField());
...
layout.row().grid(new JLabel("JLabel5")).add(new JTextField());
layout.row().center().add(new JButton("JButton"));
A form like that should be very easy to design and code by hand. Just keep reading the documentation and playing around.
Another alternative is to use a GUI Builder, Netbeans has one that really impressed me when I took a look at it last year. I don't work in Java anymore so I can't provide you with much detail.
Netbeans GUI Builder (Formerly Matisse)
I would recommed you to use NetBeans.
It's much easier since it generates code with layout manager included, so you don't have to worry about it. It's good for beginners.
I'd do a main Panel with a BorderLayout.
The south area would hold a panel with the button in it.
The center area would hold a panel with a grid layout, grid bag layout or some kind of box layout that would lay your labels and text boxes out.
I really like the JGoodies Forms tool for laying out simple (and complex) forms. It's easy to work with and has great examples. If you want something really nice looking, you can use one of their look and feels too.

Categories

Resources