Fiddle Freak
Fiddle Freak

Reputation: 2051

How to place GUI object at specific x/y place within cell within GridBagLayout

I'm new to Java Swing and am doing a small project to help me get familiar to use it. I'm trying to specify the placement dimensions of my objects (and their sizes), but I can't seem to get it right. I have the Object sizes presenting correct, but can't place them where I want. Below is an example of what it currently looks like, and what I'm looking for...

Currently...

enter image description here

Need to make it look like...

enter image description here

Below is the code I drummed up...

package Main;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import org.apache.commons.lang3.ArrayUtils;

public class StartGui extends JFrame implements ActionListener {

    private static final String[] GuiCharSelDefault = {"---  Select Character ---"};
    private static final int unselectedDefaultElement = 0;
    private static final String[] GuiCharSel = (String[])ArrayUtils.addAll(GuiCharSelDefault, Calculator.Characters);
    private String[] lvlRange = SupportMethods.createArrRange("- -", 1, 99);

    /*
     * Interactive GUI Objects
     */
    JLabel charPic;
    JComboBox charSelCombo = new JComboBox(GuiCharSel);
    JComboBox pickLvlAns = new JComboBox(lvlRange);
    JLabel nextLvlAns = new JLabel("- -");


    public StartGui() {
        /*
         * Non-Interactive GUI Objects
        */
        JPanel topFrame = new JPanel();
        JPanel bottomFrame = new JPanel();
        JPanel selPane = new JPanel();
        JLabel pickLvl = new JLabel("Pick Current Level:");
        JLabel nextLvl = new JLabel("Next Level:");

        //*******************************************************************************

        /*
         * Top Frame Settings
         */
        TitledBorder topFrameTitle;
        Border blackLine = BorderFactory.createLineBorder(Color.black);
        Border raisedBevel = BorderFactory.createRaisedBevelBorder();
        Border loweredBevel = BorderFactory.createLoweredBevelBorder();
        Border compound = BorderFactory.createCompoundBorder(raisedBevel, loweredBevel);
        topFrameTitle = BorderFactory.createTitledBorder(compound, "Character");
        topFrameTitle.setTitleJustification(TitledBorder.CENTER);
        topFrame.setBorder(topFrameTitle);
        topFrame.setLayout(new BoxLayout(topFrame, BoxLayout.X_AXIS));


        /*
         * Adds Character Picture
         */
        charPic = new JLabel("", null, JLabel.CENTER);
        charPic.setPreferredSize(new Dimension(100,100));
        topFrame.add(charPic);

        //*******************************************************************************

        /*
        * Selection Pane Settings
        */
        selPane.setLayout(new GridBagLayout());
        selPane.setBorder(blackLine);

        /*
        * Adds Character Selection ComboBox
        */
        charSelCombo.setPrototypeDisplayValue(charSelCombo.getItemAt(unselectedDefaultElement));
        selPane.add(charSelCombo, setGbc(0,0, "WEST", 0, 1, setInsets(0, 10, 0, 0)));

        /*
        * Adds "Pick Current Level:" Label
        */
        selPane.add(pickLvl, setGbc(0,1, "EAST", 0, 1, setInsets(0, 0, 0, 0)));

        /*
        * Adds "Next Level:" Label
        */
        selPane.add(nextLvl, setGbc(0,2, "EAST", 0, 1, setInsets(0, 0, 0, 0)));

        /*
        * Adds Character Current Level ComboBox
        */
        pickLvlAns.setPrototypeDisplayValue(pickLvlAns.getItemAt(lvlRange.length - 1));
        selPane.add(pickLvlAns, setGbc(1,1, "WEST", 1, 1, setInsets(0, 10, 0, 0)));

        /*
        * Adds Character Next Level Label
        */
        selPane.add(nextLvlAns, setGbc(1,2, "WEST", 1, 1, setInsets(0, 23, 0, 0)));

        //*******************************************************************************

        /*
         * BOTTOM PANE
         */
        TitledBorder bottomFrameTitle;
        bottomFrameTitle = BorderFactory.createTitledBorder(compound, "Stats");
        bottomFrameTitle.setTitleJustification(TitledBorder.CENTER);
        bottomFrame.setBorder(bottomFrameTitle);

        //*******************************************************************************

        /*
         * Display everything in GUI to user
         */
        add(topFrame, BorderLayout.NORTH);
        add(bottomFrame,BorderLayout.CENTER);

        setSize(800,600);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent arg0) {
        String charName = ((JComboBox)(arg0.getSource())).getSelectedItem().toString();
        String image = "../images/"+charName+".png";
        charPic.setIcon(new ImageIcon(new javax.swing.ImageIcon(getClass().getResource(image)).getImage().getScaledInstance(100, 100, Image.SCALE_SMOOTH)));
        charSelCombo.removeItem(GuiCharSel[unselectedDefaultElement]);
        pickLvlAns.removeItem(lvlRange[unselectedDefaultElement]);
    }

    private GridBagConstraints setGbc(int gridx, int gridy, String anchorLocation, double weightx, double weighty, Insets insets){
        GridBagConstraints gbc = new GridBagConstraints();

        if (anchorLocation.toUpperCase().equals("NORTHWEST")){
            gbc.anchor = GridBagConstraints.NORTHWEST;
        } else if (anchorLocation.toUpperCase().equals("NORTH")){
            gbc.anchor = GridBagConstraints.NORTH;
        } else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
            gbc.anchor = GridBagConstraints.NORTHEAST;
        } else if (anchorLocation.toUpperCase().equals("WEST")){
            gbc.anchor = GridBagConstraints.WEST;
        } else if (anchorLocation.toUpperCase().equals("EAST")){
            gbc.anchor = GridBagConstraints.EAST;
        } else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
            gbc.anchor = GridBagConstraints.SOUTHWEST;
        } else if (anchorLocation.toUpperCase().equals("SOUTH")){
            gbc.anchor = GridBagConstraints.SOUTH;
        } else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
            gbc.anchor = GridBagConstraints.SOUTHEAST;
        } else {
            gbc.anchor = GridBagConstraints.CENTER;
        }

        gbc.gridx = gridx;
        gbc.gridy = gridy;
        gbc.weightx = weightx;
        gbc.weighty = weighty;
        gbc.insets = insets;

        return gbc;
    }

    private Insets setInsets(int top, int left, int bottom, int right){
        Insets insets = new Insets(top,left,bottom,right);
        return insets;
    }

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

If anyone could tell me if there is a way to do this, it would really help a alot

Edit: With the help from MadProgrammer, I did some tweaking to the code above which actually made it work.

Upvotes: 0

Views: 94

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347334

weightx and weighty determine how much of the left over space is supplied to the given column/row. If you supply a weightx/y value to two or more columns/rows, the space is divided between them, so, setting the weightx of column 1 and 2, like you have, means that they share 50% of the left of space, which is why it's looking the way it is.

Instead, only the last column really needs to have a weightx value at all

Example

selPane.setLayout(new GridBagLayout());
selPane.setBorder(blackLine);

GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(2, 2, 2, 2);
charSelCombo.setPrototypeDisplayValue("Hello");
selPane.add(charSelCombo, gbc);
gbc.gridy++;
selPane.add(pickLvl, gbc);
gbc.gridy++;
selPane.add(nextLvl, gbc);

gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 1;
selPane.add(pickLvlAns, gbc);
gbc.gridy++;
selPane.add(nextLvlAns, gbc);

I simplified the code a little (for me). One of the nice things about GridBagConstraints is, GridBagLayout will make a copy of the constraints you supply, so you can share it among multiple components, like I have above, it makes it easier to update and modify, as you maintain the overall relationship between the components

Upvotes: 2

Related Questions