Search code examples
javaswinglayout-managergridbaglayout

GridBagLayout content not aligning to the right of JPanel


I have a JFrame (BorderLayout) holding a JPanel(GridBagLayout) in the South position. The JPanel border fills the screen horizontally (as I wanted it to), and so does the content within it (I don't want that).

It's much easier to visualize, so I did in Photoshop what I couldn't figure out in Java...

I made this in photoshop to demonstrate what I WANT to happen: Desired Layout This is what my code produces: What I Get

Here's the code I'm using:

private void loadTags(String filePath)
{
    Map<String, ArrayList<String>> fileTags;

    try
    {
        fileTags = PowerPointManipulator.getTagsFromFile(filePath);
    }
    catch (IOException e)
    {
        System.err.println("Could not open Powerpoint File");
        e.printStackTrace();
        return;
    }

    tag_listener = new TagButtonListener();

    pnl_tags = new JPanel();
    pnl_tags.setBackground(new Color(0, 0, 0, 0));
    pnl_tags.setLayout(new GridBagLayout());
    pnl_tags.setAlignmentX(LEFT_ALIGNMENT);

    brd_tags = new TitledBorder("Tags");
    brd_tags.setTitleColor(Color.WHITE);
    brd_tags.setBorder(new LineBorder(Color.WHITE));
    pnl_tags.setBorder(brd_tags);

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    gbc.insets = new Insets(0, 0, 2, 15);
    gbc.anchor = GridBagConstraints.FIRST_LINE_START;
    int col = 0;

    for (String key : fileTags.keySet())
    {
        ArrayList<String> vals = fileTags.get(key);
        gbc.gridwidth = 2;
        gbc.gridx = col;
        gbc.gridy = 0;

        JToggleButton tempButton = new JToggleButton(key);
        tempButton.setOpaque(false);
        tempButton.addActionListener(tag_listener);
        tempButton.setFocusable(false);

        pnl_tags.add(tempButton, gbc);

        int row = 1;

        for (String val : vals)
        {
            tempButton = new JToggleButton(val);
            tempButton.setOpaque(false);
            tempButton.addActionListener(tag_listener);
            tempButton.setFocusable(false);

            gbc.gridwidth = 1;
            gbc.gridy = row;
            pnl_tags.add(tempButton, gbc);

            row++;
        }

        col += 2;
    }

    contentPane.add(pnl_tags, BorderLayout.PAGE_END);
}

If I remove the "weight" options, then I get the proper layout, except that the buttons are centered within the JPanel.

I feel like I'm so close, but I can't get the exact right settings! Any help is much appreciated!


Solution

  • GridBagConstraints#weightx and GridBagConstraints#weighty will cause the component to occupy all the remaining space left over after all the other components have been laid out, GridBagConstraints#fill will cause the component to fill the available space of the cell it resides in based on the value you supply so,

    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    

    is doing exactly what you asked it to.

    You could try something like...

    List<String> tags = new ArrayList<>(25);
    tags.add("example");
    tags.add("objective");
    tags.add("motivation");
    tags.add("summary");
    tags.add("c");
    tags.add("*");
    tags.add("*");
    tags.add("*");
    tags.add("cs");
    
    JPanel tagPane = new JPanel(new GridBagLayout());
    tagPane.setBorder(new TitledBorder("Tags"));
    
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 3;
    gbc.gridy = 0;
    gbc.anchor = GridBagConstraints.WEST;
    for (String tag : tags) {
    
        tagPane.add(new JToggleButton(tag), gbc);
        gbc.gridx--;
        if (gbc.gridx < 0) {
            gbc.gridx = 3;
            gbc.gridy++;
        }
    
    }
    

    Which results in something like...

    Almost

    Okay, so that's a little better, but they are grouped in the center!

    Well, you could set it so each right hand side column has a weightx of 1, for example...

    gbc.gridx--;
    if (gbc.gridx < 0) {
        gbc.gridx = 3;
        gbc.gridy++;
        gbc.weightx = 1;
    } else {
        gbc.weightx = 0;
    }
    

    Or add a "filler" component to the right of all the other components...

    for (String tag : tags) {
    
        tagPane.add(new JToggleButton(tag), gbc);
        gbc.gridx--;
        if (gbc.gridx < 0) {
            gbc.gridx = 3;
            gbc.gridy++;
        }
    
    }
    JLabel filler = new JLabel();
    gbc.gridx = 4;
    gbc.gridy = 0;
    gbc.weightx = 1;
    tagPane.add(filler, gbc);
    

    Either way, you end up with something like....

    Done

    Take a closer look at How to Use GridBagLayout for more details