Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Mysterious Shrinking JScrollPane Problem

807607Jan 30 2007 — edited Jan 30 2007
I've got a slight mystery that I can't fathom, and was wondering if someone
could help me understand what I've done wrong.

I'm trying to create a simple interface within a defined width and height.
It consists of a top half, and a bottom half.

The top half is a sideways-scrolling panel containing a bunch of smaller
panels side-by-side, in a GridLayout. This can expand to fit the width of
the overall UI, but must never take more height than it actually needs to
show the smaller panels in full.

The bottom half is simply a panel, which should absorb all extra height and
width.

If I add sufficient images to NOT exceed the width of the overall UI,
everything works as expected; the JScrollPane expands to fit the images'
height into its viewport, and the filler panel below takes up the slack.

But if I add another small panel, enough to exceed the width of the overall
UI, it goes wrong; the JScrollPane shrinks to practically nothing. I have
set the preferred height of the small panels and of the panel they sit in
(which is inside the scroll pane), so it's not as if it shouldn't be able to
figure out how tall it should be; after all, it figured it out when they
didn't exceed the width.

I just can't understand why it should suddenly shrink.

Here's an applet that will demonstrate the problem:

First, the HTML file to run it:

<HTML>
<HEAD>
<TITLE>TestShrinkingScrollPane</TITLE>
</HEAD>
<BODY>
<APPLET code="JTestShrinkingScrollPaneApplet.class" width="840"
height="640"></APPLET>
</BODY>
</HTML>

Now the single java source file to compile (compiling using 1.4.1_03),
JTestShrinkingScrollPaneApplet.java :
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;

/**
 *
 */

/**
 * @author Jason
 *
 */
public class JTestShrinkingScrollPaneApplet extends JApplet
{
 /**
  *
  */
 private static final long serialVersionUID = 1L;

 public void init()
 {
  final int NUM_SMALL_PANELS = 5 ;

  // Add a panel with GridBagLayout to the content pane as our root 
component.
  JPanel backPanel = new JPanel();
  backPanel.setBackground(Color.RED);
  backPanel.setLayout(new GridBagLayout() );
  getContentPane().add(backPanel);

  // Create our panel that will scroll sideways, and its contents.
  JPanel scrollablePanel = new JPanel();
  scrollablePanel.setBackground(Color.BLUE);
  scrollablePanel.setLayout(new GridLayout(1, NUM_SMALL_PANELS, 0, 0) );
   // No gaps between cells. Unlike FlowLayout(), this forces it on to one 
row.
  for (int panelIndex = 0 ; panelIndex < NUM_SMALL_PANELS ; panelIndex++)
  {
   JPanel smallPanel = new JPanel();
   smallPanel.setBackground(Color.YELLOW);
   smallPanel.setPreferredSize(new Dimension(160, 110) );
   scrollablePanel.add(smallPanel);
  }
  // With no gaps between cells, the overall size needed is obvious:
  scrollablePanel.setPreferredSize(new Dimension(160 * NUM_SMALL_PANELS, 
110) );

  // Create the bottom panel, that will absorb the extra height available.
  JPanel fillerPanel = new JPanel();
  fillerPanel.setBackground(Color.GREEN);

  // Now create the grid bag.
  GridBagConstraints constraints = new GridBagConstraints();
  constraints.anchor = GridBagConstraints.CENTER ;
  constraints.gridheight = 1 ;
  constraints.gridwidth = 1 ;
  constraints.gridx = 0 ;
  constraints.insets = new Insets(0, 0, 0, 0);
  constraints.ipadx = 0 ;
  constraints.ipady = 0 ;
  constraints.weightx = 1.0 ;

  // The wide, scrollable panel - it can absorb the width, but must not
  // absorb any more height THAN IT NEEDS!
  constraints.fill = GridBagConstraints.HORIZONTAL ;
  constraints.gridy = 0 ;
  constraints.weighty = 0.0 ;
  backPanel.add(new JScrollPane(scrollablePanel), constraints);

  // The other panel - it can absorb the width AND the height.
  constraints.fill = GridBagConstraints.BOTH ;
  constraints.gridy = 1 ;
  constraints.weighty = 1.0 ;
  backPanel.add(fillerPanel, constraints);
 }
}
If you compile and display it as it stands, you can see the JScrollPane is
quite rightly displaying the yellow small panels in full height.

If you now change NUM_SMALL_PANELS to 6, which goes beyond the width, and
then re-display it, you'll see the scroll pane collapses.

Any ideas as to why this happens? I've tried setting the viewport preferred
size but it doesn't make any difference. The best I can do is manually set
the scroll pane's size to the needed height + a scroll bar's preferred
height but that is neither elegant nor perfect - I want to know why it goes
wrong!

Any help on the why would be appreciated.

--
Jason Teagle
jason@teagster.co.uk
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Feb 27 2007
Added on Jan 30 2007
1 comment
590 views