GridBagLayout with glue : no fixed row height

旧巷老猫 提交于 2020-05-17 07:42:53

问题


I would like to create a panel, to which I can dynamically add sub-panels with fixed height. I tried using a glue component, but it does not work. I would like to achieve that the sub-panels are visible at the top of the gridbaglayout. Side problem is that when I keep adding sub-panels, they start to overlap because the JScrollPane isn't adjusting. However, when I resize the frame, both problems are solved.

At this moment I don't see where I went wrong. Why does the glue component not take up the vertical space to push the side panels to the top?

This is my SSCCE code:

import javax.swing.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import jrdb.data.ProcessingCommand;

public class ProcessingPipelineBuilderSSCCE extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 2413084448601918744L;
    private JPanel interiorPanel = null;
    private GridBagConstraints gbc = null;
    private Component glue = null;

    public ProcessingPipelineBuilderSSCCE() {
        super("SSCCE");
        this.getContentPane().setLayout(new BorderLayout());

        gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 0, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.PAGE_START;

        JPanel pipelineBuilder = new JPanel();
        pipelineBuilder.setLayout(new GridLayout(0, 1, 0, 0));

        interiorPanel = new JPanel(new GridBagLayout());
        interiorPanel.setBorder(BorderFactory.createLineBorder(Color.red));
        JScrollPane scrollPane = new JScrollPane(interiorPanel);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setPreferredSize(new Dimension(500,300));
        pipelineBuilder.add(scrollPane);

        JButton btnNew = new JButton("Add new panel");
        btnNew.setPreferredSize(new Dimension(500, 30));
        btnNew.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (glue!=null) {
                    interiorPanel.remove(glue);
                } else {
                    glue = Box.createGlue();
                }
                gbc.gridy = gbc.gridy + 1;
                interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
                interiorPanel.add(glue,gbc);
                interiorPanel.validate();
                interiorPanel.repaint();
            }
        });
        this.getContentPane().add(btnNew, BorderLayout.PAGE_START);

        this.getContentPane().add(pipelineBuilder,BorderLayout.CENTER);


    }

    public class PipelineStep extends JPanel {
        int number;
        public PipelineStep (int n) {
            super();
            JOptionPane.showMessageDialog(interiorPanel, "adding new panel");
            this.number = n;
            this.setLayout(new FlowLayout());
            JLabel lbl = new JLabel(new Integer(this.number).toString());
            lbl.setPreferredSize(new Dimension(45,45));
            lbl.setFont(lbl.getFont().deriveFont(26));
            this.add(lbl);
            this.setPreferredSize(new Dimension(450, 50));
            this.setBorder(BorderFactory.createLineBorder(Color.green));
        }
    }

    public static void main (String args[]) {
        ProcessingPipelineBuilderSSCCE frame = new ProcessingPipelineBuilderSSCCE();
        frame.pack();
        frame.setVisible(true);
    }

}

回答1:


Why does the glue component not take up the vertical space to push the side panels to the top?

The "glue" component only has meaning when used with the BoxLayout. It has no effect with the GridBagLayout.

So my suggestion is to forget about the GridBagLayout and use the BoxLayout.

The easiest way to do this is to convert "interiorPanel" to use a vertical Box and just add your PipelineStep instances to this panel.

Try this. However, you will notice that the panels will still increase in size until the scroll pane is full, at which time you will see scrollbars appear. This is because the BoxLayout will resize components up to the maximum size of the component. So to prevent this resizing you could override the getMaximumSize() method of your PipelineStep class:

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

Or, another option is to use a "wrapper" panel for your "interiorPanel". Something like:

JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(interiorPanel, BorderLayout.PAGE_START);
//JScrollPane scrollPane = new JScrollPane(interiorPanel);
JScrollPane scrollPane = new JScrollPane(wrapper);

BorderLayout.PAGE_START respects the preferred height of the component added to it so the "interiorPanel" will always be displayed at it preferred height and scrollbars will appear when the viewport of the scroll pane is full.

I modified you code using the "wrapper" approach.

import javax.swing.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

//import jrdb.data.ProcessingCommand;

public class SSCCE1 extends JFrame {

    /**
     *
     */
    private static final long serialVersionUID = 2413084448601918744L;
//    private JPanel interiorPanel = null;
    private Box interiorPanel = null;
    private GridBagConstraints gbc = null;
    private Component glue = null;

    public SSCCE1() {
        super("SSCCE");
        this.getContentPane().setLayout(new BorderLayout());

        gbc = new GridBagConstraints();
        //gbc.insets = new Insets(5, 5, 0, 5);
        //gbc.fill = GridBagConstraints.HORIZONTAL;
        //gbc.gridx = 0;
        //gbc.gridy = 0;
        //gbc.weightx = 1.0;
        //gbc.weighty = 1.0;
        //gbc.anchor = GridBagConstraints.PAGE_START;

        JPanel pipelineBuilder = new JPanel();
        pipelineBuilder.setLayout(new GridLayout(0, 1, 0, 0));

//        interiorPanel = new JPanel(new GridBagLayout());
        interiorPanel = Box.createVerticalBox();
        interiorPanel.setBorder(BorderFactory.createLineBorder(Color.red));

        JPanel wrapper = new JPanel( new BorderLayout() );
        wrapper.add(interiorPanel, BorderLayout.PAGE_START);

//        JScrollPane scrollPane = new JScrollPane(interiorPanel);
        JScrollPane scrollPane = new JScrollPane(wrapper);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setPreferredSize(new Dimension(500,300));
        pipelineBuilder.add(scrollPane);

        JButton btnNew = new JButton("Add new panel");
        btnNew.setPreferredSize(new Dimension(500, 30));
        btnNew.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
//                if (glue!=null) {
//                    interiorPanel.remove(glue);
//                } else {
//                    glue = Box.createGlue();
//                }
                gbc.gridy = gbc.gridy + 1;
//                interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
                interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
//                interiorPanel.add(glue,gbc);
//                interiorPanel.validate();
                interiorPanel.revalidate();
                interiorPanel.repaint();
            }
        });
        this.getContentPane().add(btnNew, BorderLayout.PAGE_START);

        this.getContentPane().add(pipelineBuilder,BorderLayout.CENTER);


    }

    public class PipelineStep extends JPanel {
        int number;
        public PipelineStep (int n) {
            super();
            JOptionPane.showMessageDialog(interiorPanel, "adding new panel");
            this.number = n;
            this.setLayout(new FlowLayout());
            JLabel lbl = new JLabel(new Integer(this.number).toString());
            lbl.setPreferredSize(new Dimension(45,45));
            lbl.setFont(lbl.getFont().deriveFont(26));
            this.add(lbl);
            this.setPreferredSize(new Dimension(450, 50));
            this.setBorder(BorderFactory.createLineBorder(Color.green));
        }
    }

    public static void main (String args[]) {
        SSCCE1 frame = new SSCCE1();
        frame.pack();
        frame.setVisible(true);
    }

}


来源:https://stackoverflow.com/questions/61398928/gridbaglayout-with-glue-no-fixed-row-height

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!