Search code examples
javaswinglayout-managergridbaglayoutjdialog

Centering Spanned Columns with GridBagLayout


I have a JDialog in which I have a series of columns over which I want to center a JLabel. I cannot seem to find anything on how to do that. I can center it within a cell but not within a spanned set of columns. The labels in this image "Target" and "Change" need to be centered. Time Line Settings

Here is the SSCCE that produces this JDialog.

package stokerMonitor;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Dialog.ModalityType;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;


public class test {

static JDialog timeLineDialog;
static int row=0;

public static void main(String[] args) {
    timeLineDialog = new JDialog();
    timeLineDialog.setLayout(new GridBagLayout());
    timeLineDialog.setModalityType(ModalityType.MODELESS);
    timeLineDialog.setTitle("Time Line Settings");
    timeLineDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
    JLabel timeLabel = new JLabel("Time");
    JLabel actionLabel = new JLabel("Action");
    JLabel probeTempLabel=null;
    JLabel pitTempLabel=null;
    JLabel targetHeader=new JLabel("Target");
    Font boldFont=targetHeader.getFont().deriveFont(Font.BOLD, (float) 14);
    targetHeader.setFont(boldFont);
    JLabel changeHeader=new JLabel("Change");
    changeHeader.setFont(boldFont);
    if (Configuration.getInstance().celsius) {
        probeTempLabel = new JLabel("Temp (\u00B0 C)");
        pitTempLabel = new JLabel("Temp (\u00B0 C)");
    }
    else {
        probeTempLabel = new JLabel("Temp (\u00B0 F)");
        pitTempLabel = new JLabel("Temp (\u00B0 F)");
    }
    JLabel meatLabel=new JLabel("Meat");
    JLabel cookTimeLabel=new JLabel("Est. Time");
    JLabel weightLabel=new JLabel("Weight");
    JLabel probeLabel=new JLabel("Probe");
    JLabel pitLabel=new JLabel("Pit");
    setNewSeparator(1,row);
    GridBagConstraints gbc=makeGbc(2, row);
    gbc.gridwidth=7;
    gbc.fill=GridBagConstraints.HORIZONTAL;
    gbc.anchor=GridBagConstraints.CENTER;
    timeLineDialog.add(targetHeader,gbc);
    setNewSeparator(9,row);
    timeLineDialog.add(changeHeader,makeGbc(10, row));
    setNewSeparator(12,row++);
    setNewSeparator(1,row);
    timeLineDialog.add(timeLabel, makeGbc(2, row));
    timeLineDialog.add(probeTempLabel,makeGbc(3, row));
    timeLineDialog.add(meatLabel,makeGbc(4, row));
    timeLineDialog.add(weightLabel,makeGbc(5, row));
    timeLineDialog.add(cookTimeLabel,makeGbc(6, row));
    timeLineDialog.add(probeLabel,makeGbc(7, row));
    timeLineDialog.add(actionLabel, makeGbc(8, row));
    setNewSeparator(9,row);
    timeLineDialog.add(pitLabel,makeGbc(10, row));
    timeLineDialog.add(pitTempLabel, makeGbc(11, row++));
    setNewSeparator(12,row);
    timeLineDialog.pack();
    timeLineDialog.setLocationRelativeTo(GUI.getInstance().getFrame());
    timeLineDialog.setVisible(true);
}

static void setNewSeparator(int column_,int row_) {
    JSeparator sep=new JSeparator(SwingConstants.VERTICAL);
    sep.setPreferredSize(new Dimension(1,1));
    GridBagConstraints gbc=makeGbc(column_, row_);
    gbc.fill=GridBagConstraints.VERTICAL;
    gbc.weighty=1.;
    timeLineDialog.add(sep,gbc);
}

static GridBagConstraints makeGbc(int x, int y) {
      GridBagConstraints gbc = new GridBagConstraints();
      Insets WEST_INSETS=new Insets(5,0,5,5);
      Insets EAST_INSETS=new Insets(5,5,5,0);
      gbc.gridx = x;
      gbc.gridy = y;
      gbc.gridwidth = 1;
      gbc.gridheight = 1;

      gbc.anchor = (x == 0) ? GridBagConstraints.WEST : GridBagConstraints.EAST;
      gbc.fill = (x == 0) ? GridBagConstraints.BOTH
            : GridBagConstraints.HORIZONTAL;

      gbc.insets = (x == 0) ? WEST_INSETS : EAST_INSETS;
      gbc.weightx = (x == 0) ? 0.1 : 1.0;
      gbc.weighty = 1.0;
      return gbc;
   }
}

Can someone explain what I need to do to center those headers? TIA.


Solution

  • Tip: when debugging layouts, I find it useful to set each component to have a different background color. Then I can see the area assigned to / filled by that particular component. Most components default to a transparent background, which means their bounds is not visible. (eg targetHeader.setOpaque(true); targetHeader.setBackground(Color.RED);)

    The situation you have with your layout is that the JLabel fills the 7 columns you specified. However, the label itself draws the text it contains in the leftmost part of the space that it fills.

    There are two alternative solutions:

    1. Tell the label that you want it to center the text within the label: targetHeader.setHorizontalAlignment(JLabel.CENTER);

    2. Alternatively, you can tell the layout to not fill the space. gbc.fill=GridBagConstraints.NONE;