4

我有一个由按钮 (X)、标签 (Y) 和进度条 (Z) 组成的面板。理想情况下,我想像这样布置它们:

| X-X Y---------------Y Z---Z ============= |  <-- expanded-size panel
                              ^ extra space

| X-X Y------Y Z---Z |                         <-- reduced-size panel

上图显示:

  • 当面板展开时,标签 (Y) 应该有额外的空间,以便标签可以完全显示其文本。
  • 进度条 (Z) 应始终位于标签 (Y) 旁边。
  • 当面板缩小时,标签 (Y) 的尺寸应缩小。
  • 按钮 (X) 和进度条 (Z) 的大小应该是恒定的,而不是标签 (Y) 的大小。

但是,当我尝试使用 GroupLayout 时,面板展开时会发生这种情况:

| X-X Y---------------Y ============= Z---Z |  <-- expanded-size panel (bad)

问题是,当面板有额外空间时,标签 (Y) 会扩展超出所需的范围,这会将进度条 (Z) 推到右侧。我希望进度条的 (Z) 位置在标签 (Y) 旁边。

我怎样才能完成这个布局?

示例代码(“Blah.java”):

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

public class Blah extends JPanel {
    public Blah() {
        final JButton X = new JButton("X");
        final JLabel Y = new JLabel("yyyyyyyyyyy");
        Y.setOpaque(true);
        Y.setBackground(Color.YELLOW);
        final JProgressBar Z = new JProgressBar();
        Z.setIndeterminate(true);

        final GroupLayout l = new GroupLayout(this);
        super.setLayout(l);

        l.setHorizontalGroup(
                l.createSequentialGroup()
                .addComponent(X, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                .addComponent(Y, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(Z, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE));

        l.setVerticalGroup(
                l.createParallelGroup()
                .addComponent(X)
                .addComponent(Y)
                .addComponent(Z));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JFrame frame = new JFrame("Blah");
                frame.add(new Blah());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
4

2 回答 2

4

很少有一个单独的布局管理器可以满足您的所有需求。相反,您可以使用复合布局方法。

也就是说,将每个单独的布局要求分成一个单独的组件,并使用它自己的布局管理器。然后将所有这些添加到您的主组件中,管理整体需求。

举个例子

在此处输入图像描述在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class SimpleGridBagLayout {

    public static void main(String[] args) {
        new SimpleGridBagLayout();
    }

    public SimpleGridBagLayout() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {

            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            add(createLabel("XXX-XXX", Color.BLUE), gbc);

            JPanel panel = new JPanel();
            panel.add(createLabel("Y-Y", Color.RED));
            panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc);

            gbc.gridx++;
            gbc.weightx = 1;
            add(panel, gbc);

        }

        protected JLabel createLabel(String text, Color border) {

            JLabel label = new JLabel(text);
            label.setBorder(new LineBorder(border));
            return label;

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 100);
        }
    }

}

这里有许多因素在起作用。当可用尺寸太小时,子组件的首选尺寸和最小尺寸将对某些布局管理器在组件中的布局方式产生重大影响。

更新

public TestPane() {

    setLayout(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    add(createLabel("XXX-XXX", Color.BLUE), gbc);

    JPanel panel = new JPanel(new GridBagLayout());
    gbc = new GridBagConstraints();
    gbc.gridx = 0;
    panel.add(createLabel("Y-Y", Color.RED), gbc);
    gbc.gridx = 1;
    panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc);

    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.weightx = 1;
    add(panel, gbc);

}

更新

现在有了“不收缩”的进度条

public class TestPane extends JPanel {

    public TestPane() {

        setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        add(createLabel("XXX-XXX", Color.BLUE), gbc);

        JPanel panel = new JPanel(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        panel.add(createLabel("Y-Y", Color.RED), gbc);
        gbc.gridx = 1;
        MyProgressBar pb = new MyProgressBar();
        panel.add(pb, gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.weightx = 1;
        add(panel, gbc);

    }

    protected JLabel createLabel(String text, Color border) {

        JLabel label = new JLabel(text);
        label.setBorder(new LineBorder(border));
        return label;

    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 100);
    }
}

public class MyProgressBar extends JProgressBar {

    @Override
    public Dimension getPreferredSize() {
        Dimension ps = super.getPreferredSize();
        ps.width = 75;
        return ps;
    }

    @Override
    public Dimension getMinimumSize() {
        return getPreferredSize();
    }

}
于 2013-07-09T01:05:43.413 回答
0

在把我的头撞在墙上太久之后,我在SpringLayout's 的教程 ( http://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html ) 中发现了这个小小的文档宝石:

当组件getMaximumSizegetPreferredSize方法返回相同的值时,SpringLayout将其解释为组件不应被拉伸。

因此,通过SpringLayout手动设置Y' 和Z' 的最大尺寸,可以实现上述理想布局。这是代码:

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

public class Blah extends JPanel {
    public Blah() {
        final JButton X = new JButton("X");
        final JLabel Y = new JLabel("yyyyyyyyyyy");
        Y.setOpaque(true);
        Y.setBackground(Color.YELLOW);
        final JProgressBar Z = new JProgressBar();
        Z.setIndeterminate(true);

        final SpringLayout l = new SpringLayout();
        super.setLayout(l);

        super.add(X);
        super.add(Y);
        super.add(Z);

        Z.setMaximumSize(Z.getPreferredSize());

        l.putConstraint(SpringLayout.WEST, X, 10, SpringLayout.WEST, this);
        l.putConstraint(SpringLayout.WEST, Y, 10, SpringLayout.EAST, X);
        l.putConstraint(SpringLayout.WEST, Z, 10, SpringLayout.EAST, Y);
        l.putConstraint(SpringLayout.EAST, this, 10, SpringLayout.EAST, Z);

        l.putConstraint(SpringLayout.NORTH, X, 10, SpringLayout.NORTH, this);
        l.putConstraint(SpringLayout.NORTH, Y, 10, SpringLayout.NORTH, this);
        l.putConstraint(SpringLayout.NORTH, Z, 10, SpringLayout.NORTH, this);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JFrame frame = new JFrame("Blah");
                frame.add(new Blah());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
于 2013-07-11T01:41:06.997 回答