Jan Nielsen
Jan Nielsen

Reputation: 11799

Java Swing horizontal layout of components of varying heights

My Java 8 Swing program builds a UI dynamically based on a simple DSL:

RADIO(AAAAAAAAAAAAAAAA;one;two;three) TEXT(B) TEXT(CCCCCC) RADIO(D;four;five;six;seven;eight;9;10)

should produce a horizontal sequence of JRadioButtons and JTextFields like:

 AAAAAAAAAAAAAAAA  B             CCCCCC         D
 (*) one           [-----------] [-----------]  (*) four
 ( ) two                                        ( ) five
 ( ) three                                      ( ) six
                                                ( ) seven
                                                ( ) eight
                                                ( ) 9
                                                ( ) 10

where width and height of the text fields is the same and the radio fields vary based on values. The field types and order is completely up to the DSL.

My initial GroupLayout implementation is simple:

Group horizontalGroup = layout.createSequentialGroup();
fields.forEach(field -> horizontalGroup.addComponent(field));
layout.setHorizontalGroup(horizontalGroup);

Group verticalGroup = layout.createParallelGroup();
fields.forEach(field -> verticalGroup.addComponent(field));
layout.setVerticalGroup(verticalGroup);

and the RADIO and TEXT fields are:

private void radioField(JLabel label, List<JRadioButton> radioButtons) {
    GroupLayout gl = new GroupLayout(this);
    setLayout(gl);

    gl.setAutoCreateContainerGaps(true);

    Group horizontalGroup = gl.createParallelGroup();
    horizontalGroup.addComponent(label);
    radioButtons.forEach(radioValue -> horizontalGroup.addComponent(radioValue));

    gl.setHorizontalGroup(horizontalGroup);

    SequentialGroup verticalGroup = gl.createSequentialGroup();
    verticalGroup.addComponent(label).addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED);
    radioButtons.forEach(radioValue -> verticalGroup.addComponent(radioValue));

    gl.setVerticalGroup(verticalGroup);
}

private void textField(JLabel label, JTextField field) {
    GroupLayout gl = new GroupLayout(this);
    setLayout(gl);

    gl.setAutoCreateContainerGaps(true);

    gl.setHorizontalGroup(gl.createParallelGroup()
            .addComponent(label)
            .addComponent(field)
    );

    gl.setVerticalGroup(gl.createSequentialGroup()
            .addComponent(label)
            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(field)
    );
}

but it looks terrible is not viable:

enter image description here

While I like the simplicity of the GroupLayout, I'm starting to wonder if another layout might be needed. I'm willing to try others, especially MigLayout, but if GroupLayout can do it, all the better. Any ideas?

Upvotes: 0

Views: 1315

Answers (1)

Jan Nielsen
Jan Nielsen

Reputation: 11799

With two additional lines of code, the GridLayout implementation is now viable by linking the size of all the components:

Group horizontalGroup = layout.createSequentialGroup();
fields.forEach(field -> horizontalGroup.addComponent(field));
layout.setHorizontalGroup(horizontalGroup);

Group verticalGroup = layout.createParallelGroup();
fields.forEach(field -> verticalGroup.addComponent(field));
layout.setVerticalGroup(verticalGroup);

layout.linkSize(fields.toArray(new Component[0]));             // <-- ADDITION

and sets the maximum height of the text fields:

private void textField(JLabel label, JTextField field) {
    GroupLayout gl = new GroupLayout(this);
    setLayout(gl);

    field.setMaximumSize(new Dimension(Short.MAX_VALUE, 20));  // <-- ADDITION

    gl.setAutoCreateContainerGaps(true);

    gl.setHorizontalGroup(gl.createParallelGroup()
            .addComponent(label)
            .addComponent(field)
    );

    gl.setVerticalGroup(gl.createSequentialGroup()
            .addComponent(label)
            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(field)
    );
}

enter image description here

Upvotes: 1

Related Questions