How to center content over several panels with Mig

2019-09-16 06:16发布

问题:

I have a large panel, that contains 3 smaller panels (locationPanel, usagePanel, structuralAspectsPanel).

Each of the smaller panels has some JLabels and JCheckBoxes on them. I went ahead and centered the components on each panel, but how can I accomplish the center them over all 3 panels? (see the black line in the center please)

I have tried to use the cell-layout option in MigLayout (new JLabel("Label here"), "cell 0 0"), but was not able to create dynamically gaps of the same size, so that all components are centered. Using gap 200 (180, 300, ...) to "push" the components into a visual center seems to work, but I want to refrain from using absolute positioning / gaps, since they might break easily.

I have attached a picture of my problem:

Here is my source code:

public class RiskAssessmentPage extends JPanel {
  JPanel riskAssessmentPanel = new JPanel();

  JPanel locationPanel = new JPanel();
  JPanel usagePanel = new JPanel();
  JPanel structuralAspectsPanel = new JPanel();

  public RiskAssessmentPage() {
    setLayout(new MigLayout(""));
    riskAssessmentPanel.setLayout(
        new MigLayout("wrap", "[grow, fill]", "[grow, fill, push][grow, fill, push][grow, fill, push]"));

    locationPanel.setLayout(new MigLayout("gap rel 2", "[grow, center][grow, left]"));
    locationPanel.setBorder(BorderFactory.createTitledBorder("Location"));

    usagePanel.setLayout(new MigLayout("gap rel 2", "[grow, center][grow, left]"));
    usagePanel.setBorder(BorderFactory.createTitledBorder("Usage"));

    structuralAspectsPanel.setLayout(new MigLayout("gap rel 2", "[grow, center][grow, left]"));
    structuralAspectsPanel.setBorder(BorderFactory.createTitledBorder("Structural Aspects"));

    locationPanel.add(new JLabel("This is the first of all labels"));
    locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JSeparator(), "growx, span");
    locationPanel.add(new JLabel("Second Label"));
    locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JSeparator(), "growx, span");
    locationPanel.add(new JLabel("This Label is fairly large and long and pushes the text around"));
    locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");

    usagePanel.add(new JLabel("A label in the usage panel"));
    usagePanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JSeparator(), "growx, span");
    usagePanel.add(new JLabel("And another one and another one and another one"));
    usagePanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");

    structuralAspectsPanel.add(new JLabel("Label here"));
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JSeparator(), "growx, span");
    structuralAspectsPanel.add(new JLabel("I am so uncreative with label names..."));
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JSeparator(), "growx, span");
    structuralAspectsPanel.add(new JLabel("Thats it. I give up with naming them."));
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
    structuralAspectsPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");

    riskAssessmentPanel.add(locationPanel);
    riskAssessmentPanel.add(usagePanel);
    riskAssessmentPanel.add(structuralAspectsPanel);

    add(riskAssessmentPanel, "grow, push");
  }
}

回答1:

In order to make your panels columns line up, you need to set them to the same size. In MigLayout you can do this by setting, in this case, the first column's preferred size and growth rate to be the same value you in all the panels. For example

panel1.new MigLayout("", //Unchanged Layout Constraints
        "[:500, grow, center][grow, left]", //Column Constraints
        ""); //Unchanged Row Constraints

panel2.new MigLayout("", //Unchanged Layout Constraints
        "[:500, grow, center][grow, left]", //Column Constraints
        ""); //Unchanged Row Constraints

In this example the preferred sizes of the first column of both panel1 and panel2 are set to 500 and the growth is set at its default value so that is also the same.

A working example of what is described can be seen here

import java.awt.*;
import javax.swing.*;
import net.miginfocom.swing.MigLayout;

public class MigLay extends JFrame {

    private MigLay() {
        super("Button Layout");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new MigLayout("wrap", //Layout Constraints
        "grow, fill", //Column Constraints
        "grow, fill")); //Row Constraints
        createPanels();
        pack();
        setMinimumSize(getSize()); //Sets minimum size to the preferred size. Remove or change this line if you do not want that to happen
        setVisible(true);
    }

    private void createPanels() {

        JPanel locationPanel = new JPanel();
        JPanel usagePanel = new JPanel();
        JPanel structuralAspectsPanel = new JPanel();

        //JLabels for font metrics
        JLabel one = new JLabel("This is the first of all labels");
        JLabel two = new JLabel("Second Label");
        JLabel three = new JLabel("This Label is fairly large and long and pushes the text around");
        JLabel four = new JLabel("A label in the usage panel");
        JLabel five = new JLabel("And another one and another one and another one");

        //Font Metrics
        FontMetrics metrics = three.getFontMetrics(three.getFont()); //Take longest label manually or dynamically (You will have to add that code)
        int width = metrics.stringWidth(three.getText());

        locationPanel.setLayout(new MigLayout("gap rel 2", "[:" + width + ", grow, center][grow, left]"));
        locationPanel.setBorder(BorderFactory.createTitledBorder("Location"));

        usagePanel.setLayout(new MigLayout("gap rel 2", "[:" + width + ", grow, center][grow, left]"));
        usagePanel.setBorder(BorderFactory.createTitledBorder("Usage"));

        locationPanel.add(one);
        locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JSeparator(), "growx, span");
        locationPanel.add(two);
        locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JSeparator(), "growx, span");
        locationPanel.add(three);
        locationPanel.add(new JCheckBox("Checkbox with Label"), "wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        locationPanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");

        usagePanel.add(four);
        usagePanel.add(new JCheckBox("Checkbox with Label"), "wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JSeparator(), "growx, span");
        usagePanel.add(five);
        usagePanel.add(new JCheckBox("Checkbox with Label"), "wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");
        usagePanel.add(new JCheckBox("Checkbox with Label"), "skip, wrap");

        getContentPane().add(locationPanel);
        getContentPane().add(usagePanel);
    }

    public static void main(String[] args) {
        new MigLay();
    }
}


回答2:

I've figured it out and it's actually quite simple!

Add 0:0, grow 60 to the first column and grow 40 to the second one.

The grow 60 / 40-part means, that the left column get's 60% of the available width, while the other column gets 40%.

The 0:0-part is about setting the minimal / preferred / maximal width (although I have to admit that I dont understand it completely, explanations welcome!...I've opened a question just for this.).

Since all your panels get the same size on the left and right, they center at the same point.

locationPanel.setLayout(new MigLayout("gap rel 2", "[0:0, grow 60, center][grow 40, left]"));

usagePanel.setLayout(new MigLayout("gap rel 2", "[0:0, grow 60, center][grow 40, left]"));

structuralAspectsPanel.setLayout(new MigLayout("gap rel 2", "[0:0, grow 60, center][grow 40, left]"));