0

I've been trying to make a GUI like this:

enter image description here

However, the difficult I've run into is that I need to make the text of the buttons variable- each button should present a different option, which can vary in text length. While this itself is not difficult, I've tried countless different things but I can't get the buttons to center despite their text length. Whatever I try, I always have one of these problems:

  • The buttons don't center (there's space left at the left but they exceed the window at the right)
  • For some reason, the Question and the Goodratio change location based on the button size

I have no clue left how to do this. Does anyone have some useful intuitions on what's the best way to do this? It would be much appreciated.

EDIT: Code of the constructor function(which doesn't center correctly), which I use to set the components, as requested:

    public ButtonPannel(Test test)
{
    super();

    op1Button = new JButton("Option 1");
    op2Button = new JButton("Option 2");
    op3Button = new JButton("Option 3");
    questionText = new JLabel("Question");
    rightAndWrongAmount = new JLabel("rightAndWrongAmount");

    GridBagLayout gridBagLayout = new GridBagLayout();
    gridBagLayout.columnWidths = new int[]{30, 331, 0};
    gridBagLayout.rowHeights = new int[]{16, 0, 134, 35, 16, 0};
    gridBagLayout.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
    gridBagLayout.rowWeights = new double[]{0.0, 0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE};
    setLayout(gridBagLayout);

    JPanel panel = new JPanel();
    FlowLayout flowLayout = (FlowLayout) panel.getLayout();

    op1Button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        }
    });

    GridBagConstraints gbc_lblQuestion = new GridBagConstraints();
    gbc_lblQuestion.insets = new Insets(0, 0, 5, 0);
    gbc_lblQuestion.gridx = 1;
    gbc_lblQuestion.gridy = 1;
    add(questionText, gbc_lblQuestion);
    panel.add(op1Button);

    panel.add(op2Button);

    panel.add(op3Button);
    GridBagConstraints gbc_panel = new GridBagConstraints();
    gbc_panel.insets = new Insets(0, 0, 5, 0);
    gbc_panel.gridx = 1;
    gbc_panel.gridy = 3;
    add(panel, gbc_panel);

    GridBagConstraints gbc_lblNewLabel_1 = new GridBagConstraints();
    gbc_lblNewLabel_1.gridx = 1;
    gbc_lblNewLabel_1.gridy = 4;

    add(rightAndWrongAmount, gbc_lblNewLabel_1);

    op1Button.addActionListener(new InputHandler(test));
    op1Button.setActionCommand("1");
    op2Button.addActionListener(new InputHandler(test));
    op2Button.setActionCommand("2");
    op3Button.addActionListener(new InputHandler(test));
    op3Button.setActionCommand("3");

}

The code is generated using WindowBuilder. The problem isn't so much in the code, but more which Layout to use etc.

user3500869
  • 172
  • 1
  • 7
  • Java has **plenty** of layout managers; and for sure there is one that supports such a setup. So, simply study the corresponding tutorials; and when you have some **real** code that "almost" does the thing; feel free to ask about that. So, go here http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html or https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html first to determine which manager is for you. – GhostCat Mar 01 '17 at 08:29
  • @GhostCat As requested, added the code. Left the code out prioirly because I was more interested in the tools I needed to do it than the actual implementation of it. – user3500869 Mar 01 '17 at 08:38
  • 1
    Much better; but try to turn this into a [mcve] - so something that other people can run easily. – GhostCat Mar 01 '17 at 08:39
  • Should the buttons be equal size? I think it would look more 'balanced' if they were (and makes differences in the layouts & code). – Andrew Thompson Mar 01 '17 at 09:00

1 Answers1

4

Layouts are a little bit of black magic and trial and error. Very rarely will a single layout achieve exactly what you want, so you often need to resort to compound layouts (using multiple containers and layouts) to get what you want...

Example

So, basically, this is made of a panel, with another panel holding the buttons (and another panel acting as the "pseudo" content to add space)

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(new JLabel("Question"), gbc);
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;
            gbc.weighty = 1;
            // This is just to act as some psudo context
            add(new FillerPane(), gbc);
            gbc.fill = GridBagConstraints.NONE;
            gbc.weightx = 0;
            gbc.weighty = 0;
            add(makeButtonPane(), gbc);
            add(new JLabel("Goodratio"), gbc);
        }

        public JPanel makeButtonPane() { 
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            panel.add(new JButton("Short"));
            panel.add(new JButton("Long, long, long and lobng"));
            panel.add(new JButton("In the middle"));
            return panel;
        }

    }

    public class FillerPane extends JPanel {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

"But I want the buttons to be the same size" I hear you ask, sure, change layouts...

Another example

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(new JLabel("Question"), gbc);
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;
            gbc.weighty = 1;
            // This is just to act as some psudo context
            add(new FillerPane(), gbc);
            gbc.fill = GridBagConstraints.NONE;
            gbc.weightx = 0;
            gbc.weighty = 0;
            add(makeButtonPane(), gbc);
            add(new JLabel("Goodratio"), gbc);
        }

        public JPanel makeButtonPane() { 
            JPanel panel = new JPanel(new GridLayout(1, 0));
            panel.add(new JButton("Short"));
            panel.add(new JButton("Long, long, long and lobng"));
            panel.add(new JButton("In the middle"));
            return panel;
        }

    }

    public class FillerPane extends JPanel {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

You have to look at the layout and think about how each element relates to the others, in terms of what you want them to do, then find the layout managers which are going to help you achieve the end results and combine them together

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    Me: *"Should the buttons be equal size?.."* Pfft.. show off! – Andrew Thompson Mar 01 '17 at 09:09
  • 1
    @AndrewThompson Everybody has different feelings on the subject, I'm sure I've started a few wars with designers and other developers of such things ;) – MadProgrammer Mar 01 '17 at 09:14
  • Have you tried WindowBuilder? I always enjoy working with it, as it makes everything easier (lay-out wise) – lilienfa Mar 01 '17 at 10:49
  • @lilienfa I have tried many form builders and tend to find hand building it UIs are ultimately easier and generate better/cleaner results as a whole. I encourage all my junior developers to learn to hand code their UIs because it gives you a better understanding of how layouts work and how to break down the requirements into isolated units of work, which helps reduce the coupling and simplify the over all solution and work flow. Once you know how to do it by hand, then firm editors become a tool that can make the initial process quicker – MadProgrammer Mar 01 '17 at 18:44
  • @MadProgrammer I like your approach, and that is true :) just thought would have been easier(?) to use it:) don't know about if it is easier of not... But would be faster – lilienfa Mar 02 '17 at 07:56
  • @lilienfa From my experience, unless you understand how to leverage the layout managers, form editors just create a unmanageable mess which in the long term is almost impossible to maintain – MadProgrammer Mar 02 '17 at 08:03