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

发布于 2025-01-04 01:14:04 字数 4417 浏览 0 评论 0原文

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

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

I have an application that has multiple panels; I would like to have the freedom to use different layout managers for the different panels, but would like them to behave similarly as the window is resized by the user.

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

Running the above code, we get a window with a tabbed pane in it with three tabs. If we make the window smaller, all of them get scroll bars, as intended. If we make it larger, the three behave differently: the tab with labels only leaves them at the top left of the window, the tab with fields only centers them vertically on the left edge, and the one with the gridbag of mixed labels and fields centers them both horizontally and vertically in the enlarged window.

This is not acceptable for the application; I need to somehow make all the panels behave similarly in this way. I need them all to have scroll bars, and I would like them all to keep to the upper left if the window is made larger than the internal panel.

One other requirement: my tabs are occupied by something that extends JPanel, I've been told before I can put JScrollPane directly into the tab, but for my application I don't want to do that either. It just makes other things more complicated than they need to be.

In addition to wanting all the extra space to be put at the bottom and the right, I would dearly love to understand WHY these three situations behave differently. I still believe that we would all be better off if we understood the principles behind what we're doing, instead of just copying examples right and left and doing things by trial and error until they work.

(Incidentally, I have a GroupLayout panel that does seem to gravitate to the upper left, but didn't think it was necessary for my question and this is 100 lines of code as it is.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

╄→承喏 2025-01-11 01:14:04

似乎为了理解为什么在代码中发生这种情况,您需要理解某些术语。例如,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 的原因,您会在左侧的中心看到它们。

Seems like in order to understand why is this happening in your code, you need to understand certain terms. For example, PAGE_AXIS, LINE_AXIS, LINE_END, LINE_START and so on. Since you are providing them as constraints, these are the things that describe the orientation of the components being added to the container and their starting point, like as you writing :

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

Here you telling your BoxLayout to start adding components from the point which refers to the start of the page. (When you start your Notepad, your cursor is placed at the PAGE_AXIS on the new document). But when you are writing this :

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

Here the term anchor is used when the component is smaller than its display area. It determines where, within the display area, to place the component. But here since you mentioned that it has the value LINE_START which means :

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.

That's why the three JTextFields you created, you see them at the center on the left side.

楠木可依 2025-01-11 01:14:04

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

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

I still believe that we would all be better off if we understood the principles behind what we're doing,

See A Visual Guide to Layout Managers for working examples and explanations of the various layout managers. You need to learn how the various constraints are used for a particular layout manager.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文