为什么这三个使用GridBagLayout的面板使用不同的空间,以及如何使它们统一

时间:2012-02-09 04:02:01

标签: java swing layout-manager jtabbedpane gridbaglayout

我有一个有多个面板的应用程序;我希望可以自由地为不同的面板使用不同的布局管理器,但是希望它们的行为类似于用户调整窗口的大小。

    package example;

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

    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTabbedPane;
    import javax.swing.JTextField;

    public class TP1 extends JFrame
    {
        public static void main(String[] args)
        {
            TP1 tp1 = new TP1();
            tp1.go();
        }

        public void go()
        {
            setDefaultCloseOperation(EXIT_ON_CLOSE);

            // create a panel with some labels on it
            JPanel innerFirst = new JPanel();
            innerFirst.setLayout(new BoxLayout(innerFirst, BoxLayout.PAGE_AXIS));
            innerFirst.add(new JLabel("one"));
            innerFirst.add(new JLabel("two"));
            innerFirst.add(new JLabel("three"));
            innerFirst.add(new JLabel("four"));

            // put that panel in a scroll pane
            JScrollPane firstSP = new JScrollPane(innerFirst);

            // make another panel and put our scrolled panel in it
            JPanel outerFirst = new JPanel(); 
            outerFirst.setLayout(new BoxLayout(outerFirst, BoxLayout.PAGE_AXIS));
            outerFirst.add(firstSP); 

            // create a GridBagLayout panel with some text fields on it
            JPanel innerSecond = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = .25;
            gbc.anchor = GridBagConstraints.LINE_START;
            innerSecond.add(new JTextField(8), gbc);
            gbc.gridx = 0;
            gbc.gridy = 1;
            innerSecond.add(new JTextField(10), gbc);
            gbc.gridx =0;
            gbc.gridy = 2;
            innerSecond.add(new JTextField(12), gbc);

            // put that panel in a scroll pane
            JScrollPane secondSP = new JScrollPane(innerSecond);

            // make another panel and put our second scrolled panel in it
            JPanel outerSecond = new JPanel(); 
            outerSecond.setLayout(new BoxLayout(outerSecond, BoxLayout.LINE_AXIS));
            outerSecond.add(secondSP); 

            JPanel innerThird = new JPanel(new GridBagLayout());
            GridBagConstraints gbc3 = new GridBagConstraints();
            gbc3.anchor = GridBagConstraints.LINE_END;
            gbc.weightx = .25;
            gbc3.gridx = 0;
            gbc3.gridy = 0;
            innerThird.add(new JLabel("1st label"), gbc3);
            gbc3.gridy = 1;
            innerThird.add(new JLabel("second label"), gbc3);
            gbc3.gridy = 2;
            innerThird.add(new JLabel("IIIrd label"), gbc3);

            gbc3.anchor = GridBagConstraints.LINE_START;
            gbc3.gridx = 1;
            gbc3.gridy = 0;
            innerThird.add(new JTextField(8), gbc3);
            gbc3.gridy = 1;
            innerThird.add(new JTextField(12), gbc3);
            gbc3.gridy = 2;
            innerThird.add(new JTextField(14), gbc3);

            JScrollPane thirdSP = new JScrollPane(innerThird);
            JPanel outerThird = new JPanel();
            outerThird.setLayout(new BoxLayout(outerThird, BoxLayout.LINE_AXIS));
            outerThird.add(thirdSP);

            // put the scrolled panes onto a tabbed pane
            JTabbedPane tp = new JTabbedPane();
            tp.add("text fields", outerSecond);
            tp.add("labels", outerFirst);
            tp.add("mixed", outerThird);

            // add the tabbed pane to the frame
            this.add(tp);

            // pack it and ship it.
            pack();
            setVisible(true);
        }
    }

运行上面的代码,我们得到一个带有选项卡式窗格的窗口,其中有三个选项卡。如果我们使窗口变小,所有它们都会按预期获得滚动条。如果我们把它做得更大,那么三者的表现就不同了:带标签的标签只留在窗口的左上角,带有字段的标签只在左边缘垂直居中,而带有混合标签和字段的网格包的标签它们在放大的窗口中水平和垂直居中。

这不适用于申请;我需要以某种方式使所有面板以这种方式表现得相似。我需要它们都有滚动条,如果窗口比内部面板大,我希望它们都保持在左上方。

另外一个要求:我的标签被扩展JPanel的东西所占据,在我将JScrollPane直接放入标签之前我已被告知,但对于我的应用程序,我也不想这样做。它只是使其他事情变得比他们需要的更复杂。

除了想要将所有额外空间放在底部和右边之外,我非常希望了解为什么这三种情况表现不同。如果我们理解我们正在做的事情背后的原则,我仍然相信我们会变得更好,而不是仅仅左右复制示例,并通过反复试验做事直到他们工作。

(顺便说一句,我有一个GroupLayout面板似乎确实在左上方,但我认为这不是必要的,这是100行代码。)

2 个答案:

答案 0 :(得分:2)

  

如果我们了解我们正在做的事情背后的原则,我仍然相信我们会变得更好,

有关各种布局管理器的工作示例和说明,请参阅A Visual Guide to Layout Managers。您需要了解如何将各种约束用于特定的布局管理器。

答案 1 :(得分:2)

似乎为了理解为什么在您的代码中发生这种情况,您需要了解某些术语。例如,PAGE_AXIS,LINE_AXIS,LINE_END,LINE_START等。由于您将它们作为约束提供,因此这些内容描述了要添加到容器中的组件的方向及其起点,就像您在编写时一样:

innerFirst.setLayout(new BoxLayout(innerFirst, BoxLayout.PAGE_AXIS));

在这里,您告诉BoxLayout开始从引用页面开头的点开始添加组件。 (当您启动记事本时,光标将放在新文档的PAGE_AXIS上)。但是当你写这篇文章时:

JPanel innerSecond = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = .25;
gbc.anchor = GridBagConstraints.LINE_START;

此处,当组件小于其显示区域时,使用术语锚点。它确定在显示区域内放置组件的位置。但是在这里,因为你提到它的值为LINE_START,这意味着:

Place the component centered along the edge of its display area where lines of text 
would normally begin for the current ComponentOrientation. Equal to WEST for horizontal,
left-to-right orientations and EAST for horizontal, right-to-left orientations.

这就是你创建的三个JTextFields的原因,你可以在左侧的中心看到它们。

相关问题