GridBagLayout不稳定的大小调整和显示 [英] GridBagLayout erratic resizing and displaying

查看:162
本文介绍了GridBagLayout不稳定的大小调整和显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个在容器中使用GridBagLayout的程序.我对此的主要用途是拥有两个JPanel,分别占据窗口水平空间的75%和25%.但是由于某种原因,这两个面板看起来更像是90/10,并且在调整大小时,较小的面板会在其最小表面尺寸与我期望的25%之间迅速变化.

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%.

这是相关的代码.

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是JPanel中包含的JList.

FriendsList is a JList contained in a JPanel.

CardLayout内容主窗格中还有其他按钮和文本字段,但这些不应该影响GridBagLayout内部的内容,对吗?

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?

我制作了这个JPanel的另一个副本,作为一个独立的应用程序,它可以完美显示和调整大小.看到这里:

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?

推荐答案

weightx和weighty属性可能看起来像是比例大小,但这不是它们的作用.实际上,它们决定了布局中多余空间的分布.

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.

如果通过在JFrame上调用pack()将所有内容设置为首选大小,将没有多余的空间.这意味着weightx和weighty属性在该状态下不起作用.

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.

一旦用户开始将窗口调整为更大的大小,就会有额外的空间,只有这样,GridBagLayout才会查询weightx和weighty属性,以确定如何将额外的空间分配给每一列和每一行.在此之前,如果首选的尺寸决定了权重较小的组件比权重较大的组件完全有可能的宽度.

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();
            }
        });
    }
}

那该怎么办呢?好吧,这是GridBagLayout无法完成的一种布局方案.我会尝试使用 SpringLayout :

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);

请注意,创建listConstraints时指定的宽度参数为Spring.scale(scrollPaneWidth, 0.25f).这样可以确保列表的宽度始终是包含JTextArea的scrollPane的四分之一.

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使用起来很棘手,因为必须确保将布局容器的远端明确地链接到子组件,因为SpringLayout不会增长为自动容纳所有子组件.这就是putConstraint调用正在做的事情.

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.

这篇关于GridBagLayout不稳定的大小调整和显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆