BoxLayout Woes

A

Aaron Fude

Hi,

I have always had trouble layout out components by using BoxLayouts
because I have always found them unpredictable, if not outright buggy.
(I'm actually surprised there aren't more threads on this issue so
perhaps my understanding of this is flawed.) I have historically been
able to solve those problems by a combination of fillers, rigid boxes,
max size, min sizes, preferred size, out sizes, etc;

But now I have a problem that I am unable to solve;

I add a panel A and then a panel B to a panel C, whose layout manager
is BoxLayout(X_AXIS);
I check the min size, the pref size and the max size on A. Looking at
widths only, the preferred width is 524 and the maximum width is 462.
(By the way, that right there doesn't make sense to me.)

Then, if I only add panel A to C, its size ends up being 462. But if I
add A and B to C, then its width ends up being 524 which results in a
lot of empty space. What gives? And how to I control this behavior? I
don't set sizes anywhere in the code.

Many thanks in advance,

Aaron
 
E

Eric Sosman

Aaron said:
Hi,

I have always had trouble layout out components by using BoxLayouts
because I have always found them unpredictable, if not outright buggy.
[...]
Then, if I only add panel A to C, its size ends up being 462. But if I
add A and B to C, then its width ends up being 524 which results in a
lot of empty space. What gives? And how to I control this behavior? I
don't set sizes anywhere in the code.

May we see a short (but complete and compilable) example of
your code?
 
L

Lew

Aaron said:
I have always had trouble layout out components by using BoxLayouts
because I have always found them unpredictable, if not outright buggy.
[...]
Then, if I only add panel A to C, its size ends up being 462. But if I
add A and B to C, then its width ends up being 524 which results in a
lot of empty space. What gives? And how to I control this behavior? I
don't set sizes anywhere in the code.

     May we see a short (but complete and compilable) example of
your code?

To assist with that, see
<http://sscce.org/>

Thanks, Andrew Thompson.
 
A

Aaron Fude

Aaron said:
I have always had trouble layout out components by using BoxLayouts
because I have always found them unpredictable, if not outright buggy.
(I'm actually surprised there aren't more threads on this issue so
perhaps my understanding of this is flawed.) I have historically been
able to solve those problems by a combination of fillers, rigid boxes,
max size, min sizes, preferred size, out sizes, etc;
But now I have a problem that I am unable to solve;
I add a panel A and then a panel B to a panel C, whose layout manager
is BoxLayout(X_AXIS);
I check the min size, the pref size and the max size on A. Looking at
widths only, the preferred width is 524 and the maximum width is 462.
(By the way, that right there doesn't make sense to me.)

That doesn't make sense to me either. It depends on the components
you've added to A. Perhaps you've dome something weird?


Then, if I only add panel A to C, its size ends up being 462. But if I
add A and B to C, then its width ends up being 524 which results in a
lot of empty space. What gives?

What gives is probably in error in the code you are not showing us.
And how to I control this behavior? I
don't set sizes anywhere in the code.

Good. Nor should you IMHO.

I get consistent sizing of A at it's preferred size regardless of
whether or not I add B to C

---------------------------------------8<--------------------------------
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

/**
  * @author RedGrittyBrick
  */
public class BoxTest implements ActionListener {

     private JLabel labelA = new JLabel("this is panel A");
     private JPanel panelA;

     public static void main(String[] args) {

         final BoxTest boxTest = new BoxTest();
         Timer timer = new Timer(500, boxTest);
         timer.setInitialDelay(1000);
         timer.start();

         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
                 boxTest.createAndShowGUI();
             }
         });
     }

     void createAndShowGUI() {
         labelA.setMinimumSize(new Dimension(300, 188));   // To
         labelA.setPreferredSize(new Dimension(512, 188)); // force
         labelA.setMaximumSize(new Dimension(462, 188));   // oddity
         panelA = new JPanel();
         panelA.setBorder(new LineBorder(Color.BLUE));
         panelA.add(labelA);

         JPanel panelB = new JPanel();
         panelB.setBorder(new LineBorder(Color.RED));
         panelB.add(new JLabel("PanelB"));

         JPanel panelC = new JPanel();
         panelC.setLayout(new BoxLayout(panelC, BoxLayout.LINE_AXIS));
         panelC.add(panelA);
         //panelC.add(panelB);

         JFrame f = new JFrame("BoxTest");
         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         f.add(panelC);
         f.pack();
         f.setLocationRelativeTo(null);
         f.setVisible(true);
     }

     @Override
     public void actionPerformed(ActionEvent arg0) {
         Dimension size = panelA.getSize();
         labelA.setText(size.width + " x " + size.height);
     }}

---------------------------------------8<--------------------------------

Show us an SSCCE that reproduces the behaviour you describe.


Hi again,

I put together a little demo that shows some of the strange behavior,
although not exactly what I described in the previous post. You see
that I expand the frame, the the (red) JPanel grows to a point and the
decides to go back to it's "packed" size. What is it that I do that
could cause that? I would not be able to post a SSCCE example,
everything is too intertwined.

Here's the Demo:

http://freeboundaries.com/JPanel.html

Thanks again,

Aaron
 
R

RedGrittyBrick

[my SSCCE counter-example omitted]
Hi again,

I put together a little demo that shows some of the strange behavior,
although not exactly what I described in the previous post. You see
that I expand the frame, the the (red) JPanel grows to a point and the
decides to go back to it's "packed" size. What is it that I do that
could cause that?

I've no idea, BoxLayout has always worked in a predicable way for me.
I've seen GridBagLayout do similar things (google for totallygridbag).
I would not be able to post a SSCCE example,
everything is too intertwined.

Well either untangle it (which would be sound software engineering and a
good thing to do anyway) or create an SSCCE from scratch.

I suspect the intertwining is at the root of your problem. Remove it!


Well good, whilst that video demonstrates a strange visual effect, I
find it to be of no use in discovering exactly what in your source code
is causing that effect.

You seem to imagine that BoxLayout contains a well known bug that causes
that effect and that everyone else will say "aha that's the xxx bug,
here's a workaround." That is not the case.

An SSCCE is the best way forward. I suggest you make a copy of the
project and delete ruthlessly until you have less than 120 lines of code
that demonstrate the problem.



The following SSCCE reproduces your layout pretty exactly but does
not show the undesired effect shown in your video.
--------------------------------8<-----------------------------------
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

/**
* @author RedGrittyBrick
*/
public class BoxLayoutTest {

public static void main(String[] args) {
final BoxLayoutTest boxTest = new BoxLayoutTest();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
boxTest.createAndShowGUI();
}
});
}

void createAndShowGUI() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder("Addresses"));
panel.setBackground(Color.RED);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(new PairPanel());
panel.add(new PairPanel());

JFrame f = new JFrame("BoxTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

class PairPanel extends JPanel {
PairPanel() {
setBackground(PALE);
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(new AddressPanel());
add(Box.createHorizontalStrut(8));
add(new AddressPanel());
add(Box.createHorizontalGlue());
}
}

class AddressPanel extends JPanel {
AddressPanel() {
setBorder(new CompoundBorder(new EmptyBorder(3, 3, 3, 3), //
new LineBorder(Color.GRAY)));
setBackground(PALE);
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(1, 3, 0, 3);
gc.fill = GridBagConstraints.HORIZONTAL;

gc.anchor = GridBagConstraints.LINE_START;
gc.gridwidth = 1;
JTextField category = new JTextField(8);
category.setMinimumSize(category.getPreferredSize());
category.setBackground(Color.BLUE);
add(category, gc);
gc.gridwidth = GridBagConstraints.REMAINDER;
add(new JCheckBox("Primary"), gc);

add(new JTextField(16), gc);

add(new JTextField(16), gc);

gc.insets = new Insets(1, 3, 3, 0);
gc.gridwidth = 2;
add(new JTextField(10), gc);
gc.insets = new Insets(1, 0, 3, 0);
gc.gridwidth = 1;
add(new JLabel(", "), gc);
add(new JTextField(2), gc);
add(Box.createHorizontalStrut(10), gc);
gc.insets = new Insets(1, 3, 3, 3);
gc.gridwidth = GridBagConstraints.REMAINDER;
add(new JTextField(4), gc);

setMaximumSize(getPreferredSize()); // prevent growth
setMinimumSize(getPreferredSize()); // prevent shrink
}
}

static final Color PALE = new Color(232, 232, 232);

}
--------------------------------8<-----------------------------------
Note: I had to work hard to make stretching the frame add dead-space to
the right (as in your video) rather than adding to the length of
JTextFields or otherwise producing a more pleasing visual behaviour.
Nevertheless, it does exactly what you seem to want it to do, without "bug".
 
R

RedGrittyBrick

RedGrittyBrick wrote:

P.S. in my SSCCE change
panel.add(new PairPanel());
panel.add(new PairPanel());
to
panel.add(new PairPanel());
panel.add(Box.createVerticalStrut(5));
panel.add(new PairPanel());
 
P

public boolean

RedGrittyBrick said:
I've no idea, BoxLayout has always worked in a predicable way for me.
I've seen GridBagLayout do similar things (google for totallygridbag).

I've written my own helper class just to wrap the use of GridBagLayout
and GridBagConstraints, it can be so noisome to use.
 
P

public boolean

public said:
I've written my own helper class just to wrap the use of GridBagLayout
and GridBagConstraints, it can be so noisome to use.

Now I've got my own BoxLayout woes. I'll be posting a new thread though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,250
Latest member
Charlesreero

Latest Threads

Top