At 11:54 AM 10/23/2001 -0400, [EMAIL PROTECTED] wrote:
>I wrote a small class that shows some of the pathologic behavior I'm
>getting (see source code below). Running it produces a GUI of the
>form:
>
> ___ ___
> | | |
> | A | B |
> | | |
> |___|___|
I added more code (see below). There's now an extra button in a
new frame that dumps preferred, minimum, and actual sizes of the
various components to the console, plus the tree's preferred
scrollable viewport size.
First problem: I have no idea why the scroll pane wants to be so
tall.
Curiously, the layout behaves fine if I increase the height. It
still behaves if I decrease it, but stay above the initial height.
It's only when the height drops below the initial value that the
scroll pane decides to be narrow. If I resize back to initial
height or larger, it returns to normal.
From the dump, I see that the tree's sizes are unchanged, except
for height (expected). The JViewport containing it, and the
JScrollPane containing that in turn, are of course different in
width, but their minimum and preferred widths are also unchanged.
Sure seems like a bug to me. Unfortunately, it seems to be a bug
in GridBagLayout - a hairy beast. On that note, I decided to visit
the Bug Parade and search on "+GridBagLayout +JScrollPane". I
found 58 results. #4150133 looked pretty germane. In a nutshell,
it's not really a bug. GBL is having to layout components in a
container smaller than its preferred layout size, and is compensating.
That compensation involves looking at each component's minimum size.
JScrollPane's minimum size (in this case) is always 22x22. So it
and its inner component get shafted in the re-layout. I noticed
that each component was resized to its minimum width plus 29 pixels.
Fixing this probably isn't trivial. A smarter JScrollPane is
probably not called for: the quickest fix is to subclass it, override
getMinimumSize() to return getPreferredSize(), and use the subclass
from then on. But this breaks if the inner component is large.
A somewhat better getMinimumSize() uses getPreferredSize() up to some
limit, then uses that limit. But that will cause the same behavior
as before, just at the limit size instead of at 22x22. Plus, you're
more likely to get bad layouts from GBL clipping.
This is actually a rather interesting problem. In summary,
JScrollPane in its current form simply doesn't play well with GBL
in certain cases. In particular, if a JScrollPane contends for
space with another component whose preferred size and minimum sizes
are equal and fixed, you'll probably want to give all the resize
weight to the JScrollPane. (If you set weightx to 0 for the JPanel
in Sick, the layout behaves nicely.)
In fact, going back to your previous layout, the fixed-size panel
on top-right should get a weightx of 0. I wonder if that's enough
to fix your problem... seems simple in hindsight. The missing key
was knowing about JScrollPane's minimum size.
Here's my Sick.java, in case you want to play with it:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Sick extends JPanel {
private static JFrame frame;
private JScrollPane scroll;
private JPanel panel;
private JTree tree;
private JButton button;
public Sick() {
super();
setLayout(new GridBagLayout());
GridBagConstraints gbc;
tree = new JTree();
scroll = new JScrollPane(tree);
gbc = getBaseConstraints();
gbc.gridx = 0;
add(scroll, gbc);
panel = new JPanel();
button = new JButton("button");
panel.add(button);
gbc = getBaseConstraints();
gbc.gridx = 1;
gbc.weightx = 0;
add(panel, gbc);
}
private GridBagConstraints getBaseConstraints() {
GridBagConstraints baseGbc = new GridBagConstraints();
baseGbc.weightx = baseGbc.weighty = 1.;
baseGbc.fill = GridBagConstraints.BOTH;
baseGbc.gridy = 0;
return baseGbc;
}
public void dump()
{
System.out.println ("Preferred Viewport Size:");
System.out.println ("tree: "+tree
.getPreferredScrollableViewportSize());
System.out.println ("Preferred:");
System.out.println ("tree: "+tree .getPreferredSize());
System.out.println ("viewpt: "+scroll.getViewport().getPreferredSize());
System.out.println ("scroll: "+scroll.getPreferredSize());
System.out.println ("panel: "+panel .getPreferredSize());
System.out.println ("button: "+button.getPreferredSize());
System.out.println ("Minimum:");
System.out.println ("tree: "+tree .getMinimumSize());
System.out.println ("viewpt: "+scroll.getViewport().getMinimumSize());
System.out.println ("scroll: "+scroll.getMinimumSize());
System.out.println ("panel: "+panel .getMinimumSize());
System.out.println ("button: "+button.getMinimumSize());
System.out.println ("Actual:");
System.out.println ("tree: "+tree .getSize());
System.out.println ("viewpt: "+scroll.getViewport().getSize());
System.out.println ("scroll: "+scroll.getSize());
System.out.println ("panel: "+panel .getSize());
System.out.println ("button: "+button.getSize());
}
public static void main(String[] args) {
frame = new JFrame();
final Sick s = new Sick();
frame.getContentPane().add(s, "Center");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.show();
JFrame cf = new JFrame();
JButton b = new JButton("dump");
cf.getContentPane().add (b);
cf.setBounds (200,200,100,100);
cf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
b.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e)
{
s.dump();
}
});
cf.show();
}
}
_______________________________________________
Swing mailing list
[EMAIL PROTECTED]
http://eos.dk/mailman/listinfo/swing