GridBagLayout erratic resizing and displaying

你说的曾经没有我的故事 提交于 2020-01-06 21:21:49

问题


I'm making a program that uses a GridBagLayout in a container. My primary use for this is to have two JPanels, which occupy 75% and 25% of the horizontal space of the window. For some reason though, the two panels look more like 90/10, and when resizing, the smaller one rapidly changes in size, between it's apparent minimum size, and what I believe is the desired 25%.

Here is the relevant code.

frmReedreadV = new JFrame();
    frmReedreadV.setBounds(x, y, width, height);
    frmReedreadV.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frmReedreadV.getContentPane().setLayout(new BoxLayout(frmReedreadV.getContentPane(), BoxLayout.Y_AXIS));

    JPanel stretchyPanel = new JPanel();
    frmReedreadV.getContentPane().add(stretchyPanel);
    stretchyPanel.setLayout(new CardLayout(0, 0));

    JPanel textAndUsers = new JPanel(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.fill = GridBagConstraints.BOTH;

    gbc.weighty = 1;

    textArea = new JTextArea();
    textArea.setMargin(new Insets(2, 5, 5, 2));
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);

    scrollPane = new JScrollPane(textArea);
    scrollPane.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));

    gbc.weightx = 0.8;
    textAndUsers.add(scrollPane, gbc);

    list = new FriendsList(listUpdate);

    gbc.weightx = 0.2;
    textAndUsers.add(list.frmUserList, gbc);

    stretchyPanel.add(textAndUsers);

FriendsList is a JList contained in a JPanel.

There are other buttons and text fields in the main CardLayout content pane, but those shouldn't affect what is inside of this GridBagLayout, correct?

I made another copy of this JPanel as a standalone application, and it displays and resizes perfectly. See here:

JFrame frame = new JFrame();
    frame.getContentPane().setLayout((new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds(100, 100, 550, 600);

    JPanel stretchyPane = new JPanel();
    frame.getContentPane().add(stretchyPane);
    stretchyPane.setLayout(new CardLayout(0, 0));

    JPanel panel = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    JTextArea text = new JTextArea();
    text.setMargin(new Insets(2, 5, 5, 2));
    JScrollPane panel1 = new JScrollPane(text);
    FriendsList panel2 = new FriendsList(new Object());

    c.fill = GridBagConstraints.BOTH;
    c.weightx = .8;
    c.weighty = 1;
    panel.add(panel1, c);
    c.weightx = .2;
    //c.fill = GridBagConstraints.HORIZONTAL;
    panel.add(panel2.frmUserList, c);

    stretchyPane.add(panel);

    frame.setVisible(true);

What could be causing the difference between the two, since I've replicated my original line by line into the copy?


回答1:


The weightx and weighty properties might appear to act as proportional sizes, but that is not what they do. In fact they determine the distribution of extra space in the layout.

If you set everything to its preferred size by calling pack() on your JFrame, there will be no extra space. Which means the weightx and weighty properties have no effect while it's in that state.

Once the user starts resizing the window to be larger, there will be extra space, and only then will GridBagLayout consult the weightx and weighty properties to determine how to apportion that extra space to each column and row. Until then, it's entirely possible for a component with a small weightx to be wider than a component with a larger weightx, if their preferred sizes dictate it.

Hopefully this simple program will demonstrate this concept. Try using the mouse (or keyboard) to resize the window to be wider, and observe how each of the textfields grows:

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class GridBagProportions {
    static void buildAndShowWindow() {
        JTextField small = new JTextField("small (0.8)", 5);
        JTextField large = new JTextField("LARGE (0.2)", 30);

        small.setMinimumSize(small.getPreferredSize());
        large.setMinimumSize(large.getPreferredSize());

        JPanel panel = new JPanel(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets.left = 6;
        gbc.insets.top = 6;
        gbc.insets.bottom = 6;

        gbc.weightx = 0.8;
        panel.add(small, gbc);

        gbc.weightx = 0.2;
        gbc.insets.right = 6;
        panel.add(large, gbc);

        JFrame frame = new JFrame("GridBagLayout Proportions");
        frame.getContentPane().add(panel);
        frame.pack();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildAndShowWindow();
            }
        });
    }
}

So what can be done about it? Well, this is one layout scenario that GridBagLayout cannot do. I would try using a SpringLayout:

SpringLayout layout = new SpringLayout();
JPanel textAndUsers = new JPanel(layout);

SpringLayout.Constraints scrollPaneConstraints =
    new SpringLayout.Constraints(scrollPane);

Spring scrollPaneWidth = scrollPaneConstraints.getWidth();
SpringLayout.Constraints listConstraints =
    new SpringLayout.Constraints(scrollPaneWidth,
                                 scrollPaneConstraints.getY(),
                                 Spring.scale(scrollPaneWidth, 0.25f),
                                 scrollPaneConstraints.getHeight());

layout.putConstraint(SpringLayout.EAST, textAndUsers, 0,
                     SpringLayout.EAST, frmUserList);
layout.putConstraint(SpringLayout.SOUTH, textAndUsers, 0,
                     SpringLayout.SOUTH, scrollPane);

textAndUsers.add(scrollPane, scrollPaneConstraints);
textAndUsers.add(frmUserList, listConstraints);

Notice that the creation of listConstraints specifies a width argument which is Spring.scale(scrollPaneWidth, 0.25f). This ensures the list is always one-fourth as wide as the scrollPane containing the JTextArea.

SpringLayout is tricky to use, in that you have to make sure to link the far edges of the layout container to child components explicitly, because SpringLayout won't grow to accommodate all the child components automatically. That's what the putConstraint calls are doing.



来源:https://stackoverflow.com/questions/30495188/gridbaglayout-erratic-resizing-and-displaying

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!