提问者:小点点

我应该使用什么设置来解决这个GridBagLayout大小调整问题?


我一直在寻找并尝试解决GridBagLayout调整大小时遇到的问题,但无济于事。问题是:

>

  • 我向下拖动JDialog窗口的底部以使其更高;搜索面板(下面屏幕截图中的上方面板)不断变得更高,只是添加了它不需要的内容空白(我不想要这个浪费的空间,它会占用下面滚动表的高度)。

    如果我移动窗口的右侧使其变窄,滚动面板会变得太短,即使我的屏幕和窗口可以显示其全部高度;出现垂直滚动条(我不喜欢面板垂直滚动,只是水平滚动。)

    我的JDialog在右上角保存下面的组件,使用下面的布局管理器和约束:

    JPanel      level 1         uses GridBagLayout Setting 1 (see below)
    JScrollPane level 2         uses GridBagLayout Setting 1  
    JPanel      level 3         uses GridBagLayout Setting 2
    JPanel      level 4         uses GridBagLayout Setting 2
    JPanel      level 5         uses GridBagLayout Setting 2
    JPanel      level 5         uses GridBagLayout Setting 2
    

    GridBagLayout. GridBagConstraint(c)

    设置1:

    c.fill = GridBagConstraints.BOTH;
    c.weightx = 99.0;
    c.weighty = 99.0;
    

    设置2:

    c.fill = GridBagConstraints.NONE;
    c.weightx = 1.0;
    c.weighty = 1.0;
    

    最初,如果我不使用JScrollPane,这是我的JDialog

    如果我拖动窗口使其变大,JPanel的大小(在我使用JScrollPane使其可水平滚动之前使用的大小)保持不变。我想实现相同的行为,只是我想使其可水平滚动。

    我应该使用什么布局管理器来解决这个大小调整问题?如果我必须真正使用GridBagLayout,我应该使用什么约束/设置?我将非常感谢任何建议。谢谢!

    更新1 ------------------------------------------------------

    请检查下面的示例代码场景。两个可滚动面板(RED和BLUE)都使用GridBagConstrats. BOTH屁屁屁屁等于99.0。我希望红色面板的高度足以包含文本字段。我还希望当对话框被向下拖动以使窗口更大时,红色面板的高度保持不变。请注意,在实际屏幕中,两个面板的内容数量可能会发生变化(存在添加/减按钮),因此,设置最小面板大小(用于调整大小)无济于事。请建议我应该如何处理这种情况。谢谢!

    package cfr.view.search;
    
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    
    import javax.swing.JDialog;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextField;
    import javax.swing.border.EmptyBorder;
    
    public class GBLSample extends JDialog {
    
        private JPanel contentPane;
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        GBLSample frame = new GBLSample();
                        frame.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * Create the frame.
         */
        public GBLSample() {
            setBounds(100, 100, 350, 400);
            contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            setContentPane(contentPane);
            GridBagLayout gbl_contentPane = new GridBagLayout();
            contentPane.setLayout(gbl_contentPane);
    
            // RED PANEL ------------------------------------------------ 
            JScrollPane sp1 = new JScrollPane();
            GridBagConstraints gbc1 = new GridBagConstraints();
            gbc1.fill = GridBagConstraints.BOTH;
            gbc1.weightx = 99.0;
            gbc1.weighty = 99.0;
            contentPane.add(sp1, gbc1);
    
            JPanel redPanel = new JPanel();
            redPanel.setBackground(Color.RED);
            JTextField field = new JTextField(20);
            GridBagConstraints gbc2 = new GridBagConstraints();
            gbc2.anchor = GridBagConstraints.PAGE_START;
            gbc2.fill = GridBagConstraints.NONE;
            contentPane.add(field, gbc2);
    
            redPanel.add(field);
            sp1.setViewportView(redPanel);
    
            // BLUE PANEL ------------------------------------------------ 
            JScrollPane sp2 = new JScrollPane();
            GridBagConstraints gbc3 = new GridBagConstraints();
            gbc3.fill = GridBagConstraints.BOTH;
            gbc3.gridx = 0;
            gbc3.gridy = 1;
            gbc3.weightx = 99.0;
            gbc3.weighty = 99.0;
            contentPane.add(sp2, gbc3);
    
            JPanel bluePanel = new JPanel();
            bluePanel.setBackground(Color.BLUE);
            sp2.setViewportView(bluePanel);
        }
    }
    

    更新2 ------------------------------------------------------

    JPanel的大小调整仍然存在与上面#1相同的问题。问题1


  • 共3个答案

    匿名用户

    试试这段代码:

    package test;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.border.EmptyBorder;
    
    public class GridBagLayoutSample extends JFrame {
    
    private JPanel contentPane;
    
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    GridBagLayoutSample frame = new GridBagLayoutSample();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    /**
     * Create the frame.
     */
    public GridBagLayoutSample() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[]{0, 0};
        gbl_contentPane.rowHeights = new int[]{50, 0, 0};
        //the 1.0 value in columnWeights let redPanel and scrollPane (that contain bleuPanel) grow horizontally
        //the 1.0 value is in the first index so it affect the first column
        //you still need to use a valid value for gbc_redPanel.fill and gbc_scrollPane.fill;
        gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
        //the 0.0 value of rowWeights => components in first row will not grow
        //the 0.0 value of rowWeights => components in second row will grow
        gbl_contentPane.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
        contentPane.setLayout(gbl_contentPane);
    
        JPanel redPanel = new JPanel();
        redPanel.setBackground(Color.RED);
        GridBagConstraints gbc_redPanel = new GridBagConstraints();
        gbc_redPanel.insets = new Insets(0, 0, 5, 0);
        gbc_redPanel.fill = GridBagConstraints.BOTH;
        gbc_redPanel.gridx = 0;
        gbc_redPanel.gridy = 0;
        contentPane.add(redPanel, gbc_redPanel);
    
        JScrollPane scrollPane = new JScrollPane();
        GridBagConstraints gbc_scrollPane = new GridBagConstraints();
        gbc_scrollPane.fill = GridBagConstraints.BOTH;
        gbc_scrollPane.gridx = 0;
        gbc_scrollPane.gridy = 1;
        contentPane.add(scrollPane, gbc_scrollPane);
    
        JPanel bleuPanel = new JPanel();
        bleuPanel.setBackground(Color.BLUE);
        //scrollpane work with the preferred size of the component in the viewportView
        //try to change this values
        bleuPanel.setPreferredSize(new Dimension(400, 400));
        scrollPane.setViewportView(bleuPanel);
    }
    

    }

    将此添加到您的代码

    gbl_contentPane.rowHeights = new int[]{40, 0, 0};
    gbl_contentPane.rowWeights = new double[]{0.0,0.0, 1.0, Double.MIN_VALUE};
    gbc1.gridx = 0;
    gbc1.gridy = 0;
    

    并删除此

    gbc1.weightx = 99.0;
    gbc1.weighty = 99.0;
    

    匿名用户

    也许GridBagLayout可能不适合您当前的UI,而BorderLayout会更好?将红色面板放在BorderLayout. NORTH中,将蓝色面板放在BorderLayout.CENTER中。当您调整对话框大小时,CENTER区域中的组件将增长和缩小,当您 /-项目时,红色面板的首选大小将得到尊重。

    匿名用户

    我一直在寻找并尝试解决GridBagLayout调整大小时遇到的问题,但无济于事。

    欢迎使用GridBagLayout

    首先要注意的是在

            JPanel redPanel = new JPanel();
            redPanel.setBackground(Color.RED);
            JTextField field = new JTextField(20);
    //      GridBagConstraints gbc2 = new GridBagConstraints();
    //      gbc2.anchor = GridBagConstraints.PAGE_START;
    //      gbc2.fill = GridBagConstraints.NONE;
    //      contentPane.add(field, gbc2);
    
            redPanel.add(field);
            sp1.setViewportView(redPanel);
    

    您正在将文本字段添加到内容窗格中,然后将其再次添加到面板中,这会覆盖您之前的分配(一个组件只能属于一个容器)。我注释掉了不起作用的行。在红色面板中如何布局文本字段的选择与在内容窗格中如何布局红色面板的选择完全不同。

    我希望红色面板的高度足以包含文本字段。

    这是由布局管理器处理的。但是,如果您手动调整窗口大小以使面板没有足够的空间,那么如果面板位于JScrollPane中,则会出现滚动条。您可以尝试将面板的最小getumSize设置为其getPreferredSize,但我相信并非所有布局管理器都尊重它。

    无论如何,我不明白为什么你需要红色面板的滚动窗格。

    我还希望当对话框被拖动以使窗口变大时,红色面板的高度保持不变。

    然后您应该将其权重设置为0

    注意:不要根据Java命名约定在非最终变量名中使用下划线(_)(gbl_contentPane应该是gblContentPane)。

    编辑

    这是一个动态更改redPanel分配大小的示例。为了简单起见,我使用BorderLayout作为内容窗格(也由Dan O建议)。

    public class GBLSample extends JDialog {
    
        private JPanel contentPane;
        private JScrollPane redSP = new JScrollPane(new RedPanel());
    
        public static void main(String[] args) {
    
            EventQueue.invokeLater(() -> {
                GBLSample frame = new GBLSample();
                frame.setVisible(true);
            });
        }
    
        private class RedPanel extends JPanel {
    
            RedPanel() {
    
                setLayout(new GridBagLayout());
                setBackground(Color.RED);
    
                GridBagConstraints c = new GridBagConstraints();
                c.anchor = GridBagConstraints.FIRST_LINE_START;
                add(new JTextField(10), c);
                c.weightx = 1;
                c.gridx = 1;
                add(new JComboBox<>(), c);
                c.weightx = 0;
                c.gridx = 0;
                add(new JComboBox<>(), c);
                c.gridx = 1;
                add(new JComboBox<>(), c);
                c.weighty = 1;
                c.gridx = 0;
                c.gridy = 2;
                add(new JButton("SSSS"), c);
            }
    
            @Override
            public Dimension getPreferredSize() {
    
                Dimension dim = super.getPreferredSize();
                JScrollBar sb = redSP.getHorizontalScrollBar();
                if (!sb.isShowing())
                    return dim;
                return new Dimension(dim.width, dim.height + sb.getHeight());
            }
        }
    
        public GBLSample() {
    
            setBounds(100, 100, 350, 400);
            contentPane = new JPanel(new BorderLayout());
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            setContentPane(contentPane);
    
            // RED PANEL ------------------------------------------------
            redSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
            contentPane.add(redSP, BorderLayout.PAGE_START);
    
            // BLUE PANEL ------------------------------------------------
            JPanel bluePanel = new JPanel();
            bluePanel.setBackground(Color.BLUE);
            contentPane.add(new JScrollPane(bluePanel));
        }
    }
    

    这个想法是通过给底部的一个组件所有的重量来增加面板底部的所有额外空间(同样可以用最右边的组件来完成x轴)。当显示滚动条时,面板重新计算它的高度,并将滚动条的高度添加到自身(到最下面的组件),然后滚动条不会隐藏任何东西。