Question

I'm trying to design a JButton (an "Ok" button) that to look good has to be horizontally centered in the containing JFrame.
I'm using the GUI Builder with the Free Form layout (GroupLayout).

I've taken several GUI builder tutorials (http://netbeans.org/kb/docs/java/quickstart-gui.html) but haven't found this topic. In other gui builders (delphi) this can be done by removing the anchors from both edges.

Was it helpful?

Solution

If you want your component to remain centered in its container if the container is resized, you have several options available to you, but I don't think that GroupLayout is one of them (please correct me if I'm wrong). One way is to change the container's layout to GridBagLayout, and then simply add the JButton into it without any constraints.

OTHER TIPS

GroupLayout does support centering of components. It is a very capable layout manager. I personally put it after the MigLayout manager and before the FormLayout manager.

In the following three examples, we have a panel and a button. The button is horizontally centered.

Centering with NetBeans Builder

To center a component using a Netbeans Builder, we need to create horizontal resizable gaps from both sides of the button.

The green area of the screenshot is a currently selected gaps. The strings inside the gaps suggest that it is a resizable gap.

NetBeans screenshot

The gaps are automatically added when we place components on the form. To define a gap to be resizable, we right click on the gap and select the "Edit Layout Space" option. We get the following dialog:

NetBeans screenshot

To get a resizable gap, we check the Resizable check box.

Centering manually by using a parallel group

Components can be centered in the parallel group by passing the GroupLayout.Alignment.CENTER parameter.

package com.zetcode;

import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GroupLayoutCenter extends JFrame {

    public GroupLayoutCenter() {

        initUI();

        setTitle("Centered button");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);        
    }

    private void initUI() {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);    

        gl.setAutoCreateGaps(true);
        gl.setAutoCreateContainerGaps(true);

        JPanel pnl = new JPanel();
        pnl.setBorder(BorderFactory.createEtchedBorder());

        JButton btn = new JButton("Button");

        gl.setHorizontalGroup(gl.createParallelGroup(CENTER)
           .addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
           .addComponent(btn)
        );

        gl.setVerticalGroup(gl.createSequentialGroup()
           .addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
           .addComponent(btn)            
        );          

        pack();
    }


    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                GroupLayoutCenter ex = new GroupLayoutCenter();
                ex.setVisible(true);
            }
        });
    }
}

Centering manually by using gaps

This solution is what NetBeans generated code does. We place two resizable gaps to the left and right sides of the button.

package com.zetcode;

import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GroupLayoutCenter2 extends JFrame {

    public GroupLayoutCenter2() {

        initUI();

        setTitle("Centered button");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);        
    }

    private void initUI() {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);    

        gl.setAutoCreateGaps(true);
        gl.setAutoCreateContainerGaps(true);

        JPanel pnl = new JPanel();
        pnl.setBorder(BorderFactory.createEtchedBorder());

        JButton btn = new JButton("Button");

        gl.setHorizontalGroup(gl.createParallelGroup()
                .addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
                .addGroup(gl.createSequentialGroup()
                        .addGap(5, 100, Short.MAX_VALUE)
                        .addComponent(btn)
                        .addGap(5, 100, Short.MAX_VALUE))
        );

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
                .addComponent(btn)
        );    

        pack();
    }


    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                GroupLayoutCenter2 ex = new GroupLayoutCenter2();
                ex.setVisible(true);
            }
        });
    }
}

enter image description here

Try GridbagLayout See this

Try another LayoutManager! GroupLayout is very obscure when just looking at the code generated by NetBeans.

If you used DesignGridLayout then what you need is as simple as:

DesignGridLayout layout = new DesignGridLayout(container);
layout.row().center().add(okButton);

javax.swing.Box.Filler can be used to pad space around a component inside a GroupLayout. In NetBeans Matisse (GUI Builder) they're called 'Horizontal Strut' under the 'Swing Fillers' section of the palette. Just put one on either side of your button, size them to fill all the empty space between the button and the edge of the container, and make sure they're both flagged to Auto Resize Horizontally.

As for using another LayoutManager, I know people don't like GroupLayout because it is not conducive to manual coding. That is by design. As the docs say, GroupLayout is intended to be used by GUI builders. So as long as you're ok with tying yourself to using NetBeans & Matisse for the life of your GUI, GroupLayout is really the best option.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top