OK, with a lot of help I discovered a solution, along with some more
crazy stuff.  To recap, the problem is illustrated by the following
snippet:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class BuggySwing extends JPanel {

  private JLabel messageBar;
  private GridBagConstraints gbc;
  private JButton button;
  private JPanel panel;
  private DefaultListModel listModel;
  private JList list;
  private JScrollPane scrollPane;
  private boolean emptyList = true;

  public BuggySwing() {
    super();
    setLayout(new GridBagLayout());

    gbc = getBaseConstraints();
    gbc.gridx = 0; gbc.gridy = 0;
    gbc.gridheight = GridBagConstraints.REMAINDER;
    add(new JTextArea("Some text"), gbc);

    button = new JButton("Toggle");
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        listModel.clear();
          if(emptyList) {
            emptyList = false;
            listModel.addElement("one list item");
            messageBar.setText(null);
          }
          else {
            emptyList = true;
            messageBar.setText("The list is empty");
          }
        }
      });

    panel = new JPanel();
    panel.add(button);

    gbc = getBaseConstraints();
    gbc.gridx = 1; gbc.gridy = 0;
    gbc.weighty = 0.;
    add(panel, gbc);

    listModel = new DefaultListModel();
    list = new JList(listModel);
    emptyList = true;
    scrollPane = new JScrollPane(list);

    gbc = getBaseConstraints();
    gbc.gridx = 1; gbc.gridy = 1;
    gbc.weighty = 1.;

    add(scrollPane, gbc);
  }

  private GridBagConstraints getBaseConstraints() {
    GridBagConstraints baseGbc = new GridBagConstraints();
    baseGbc.weightx = baseGbc.weighty = 1.;
    baseGbc.fill = GridBagConstraints.BOTH;
    return baseGbc;
  }

  private static JLabel makeMessageBar() {
    JLabel label = new JLabel();
    int width = (int) (label.getPreferredSize().getWidth());
    int height = label.getFontMetrics(label.getFont()).getHeight();
    label.setPreferredSize(new Dimension(width, height));
    return label;
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame();
    BuggySwing panel = new BuggySwing();
    panel.messageBar = makeMessageBar();
    panel.messageBar.setText("The list is empty");

    frame.getContentPane().add(panel.messageBar, "South");
    frame.getContentPane().add(panel, "Center");
    
    frame.pack();
    frame.show();
  }
}

First, as an illustration that there's at least one bug afoot,
after I posted my last post, I serendipitously discovered that getting
rid of the lines that cause the change in the contents of the *message
bar* also gets rid of the unwanted resizing of components:

    ...
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        listModel.clear();
          if(emptyList) {
            emptyList = false;
            listModel.addElement("one list item");
      //    messageBar.setText(null);
          }
          else {
            emptyList = true;
      //    messageBar.setText("The list is empty");
          }
        }
      });

(Unfortunately, this is no solution, since an unchanging message bar is
useless--and I need a message bar).

The message bar is not even within the purview of the GridBagLayout.
If this is not a bug, I don't know what is.


Next, I had been told in earlier posts that the important parameter
when using a ScrollPane within a GridBagLayout was minimumSize, not
preferredSize, so before posting my last post I had tried:

    scrollPane = new JScrollPane(list);
    scrollPane.setMinimumSize(scrollPane.getPreferredSize());

This appeared to work, but only if the user did not resize the window
in such a way that its *height* increased (there's another bit of
GridBagLayout crazy magic for ya!).

Later, after posting, in desperation I finally replaced the above line
with the crazy-looking

    scrollPane = new JScrollPane(list);
    scrollPane.setPreferredSize(scrollPane.getPreferredSize());

and this seems to work, even after resizing, and with a functional
message bar.

In other words, explicitly setting the preferredSize (only once) to
the value it supposedly *already has* causes the behavior to change.
This gem is also completely undocumented, as far as I can tell.

It's really a shame.  It took me 2 1/2 workdays (not including the
time of posters who offered their analysis and suggestions) to sort
this out.  (Kind of: many mysteries remain.)

Anyway, *many many* thanks for your help.

KJ
_______________________________________________
Swing mailing list
[EMAIL PROTECTED]
http://eos.dk/mailman/listinfo/swing

Reply via email to