3

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

    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 行代码。)

4

2 回答 2

2

我仍然相信,如果我们了解我们所做工作背后的原则,我们都会过得更好,

有关各种布局管理器的工作示例和说明,请参阅布局管理器的视觉指南。您需要了解如何将各种约束用于特定布局管理器。

于 2012-02-09T04:33:41.087 回答
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您创建的三个,您会在左侧的中心看到它们。

于 2012-02-09T09:45:22.710 回答