1

solid, recommended way of placing components exactly where wanted on a JFrame?

In my case I have a simple Jframe acting as a menu. The frame consists of a label at the top and three buttons in the middle. Using free design the 3 buttons seem to float over the frame and when i run the project they shift into ugly looking positions. Only when the 3 buttons are dragged to maximum length (to each side of the frame) will they behave as "locked in place". This is very ugly.. I would like the 3 buttons centered in the middle of the frame together.

Im using Netbeans. Free design is what I have been using but it is only good when there are alot of components so they can "snap in" to each others positions. Using other set layout managers hasent worked. How would someone with experience deal with such a problem?

I am interested in thorough learning. If this question is painfully amateur could someone at least recommend a text book or other source of GUI learning? (I have been over "Objects first with java" twice and they only have very basic explanations of GUI building in there).

Thanks for any direction.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Dylan
  • 31
  • 1
  • 4
  • "Objects first with java" isn't even trying to teach you real GUI. Search the web, there are plenty of tutorials out there. – keyser Oct 11 '12 at 08:34
  • read the Swing Trail in tutorial referenced in the swing tag wiki, in particular the chapter about using LayoutManagers (you need them and they solve _all_ layout problems, really :-) – kleopatra Oct 11 '12 at 09:53

2 Answers2

6

The thing is pretty simple, but of course, you should search a little more by yourself.

By the way, you're is a problem with the managing of the layout and size of the buttons.

Forget please to use any layout creator, because they generate a confuse code and it's not good to understand what really is happening.

Usually for the beginners I talk about a specific layout, that is BoxLayout [edit: of course there are many easier way to reach the goal, this answer have a teaching purpose and want to be large enough to be understood, not just to be a "here, do this copy-paste]

First of all we need to know how Box layout works. It have two kind of AXIS (that is the way you will have the Components added positioned) that are top to bottom (PAGE_AXIS) and left to right (LINE_AXIS). Using this two axis and nesting various layout you can to pretty well whatever you want.

The first thing to know is how to nest more layout.

To nest the layout we will work with JPanel, each with a different axis that will be putted one inside another.

Start analyzing your case. You have a label over three buttons in the center of your panel. We can start from the inner panel, the one with the Components; we need a PAGE_AXIS (top to botton) that will include:

// +---------------------+
// |     white space     |
// |                     |
// + - - - - - - - - - - +
// |JLABEL JLABEL  JLABEL|
// + - - - - - - - - - - +
// |     white space     |
// |_____________________|
// |       button        |
// |---------------------|
// |_____________________|
// |       button        |
// |---------------------|
// |_____________________|
// |       button        |
// |---------------------|
// |     white space     |
// +---------------------+

As you can see the Panel is fitted to match the width of the components, the trick is that BoxLayout prefer to give the component its maximum size. In this case there are no margins, so we need a external different JPanel, with LINE_AXIS, in order to put left and right margins, the result will be this:

// +---+---------------------+---+
// |   |     white space     |   |
// |   |                     |   |
// |   + - - - - - - - - - - +   |
// | W |JLABEL JLABEL  JLABEL| W |
// | H + - - - - - - - - - - + H |
// | I |     white space     | I |
// | T  _____________________  T |
// | E |       button        | E |   
// |    ---------------------    |
// | S  _____________________  S |
// | P |       button        | P |   
// | A  ---------------------  A |
// | C  _____________________  C |
// | E |       button        | E |   
// |    ---------------------    |
// |   |     white space     |   |
// +-----------------------------+

So, the first thing we need to know is hot to set up the layout for each panel.

// Initializing
JPanel outside = new JPanel();
JPanel inside = new JPanel();

// setting a layout with horizontal alignment
outside.setLayout(new BoxLayout(outside, BoxLayout.LINE_AXIS));
// setting a layout with vertical alignment
inside.setLayout(new BoxLayout(inside, BoxLayout.PAGE_AXIS));

Once done this we must fill the panel. Starting from the outside. The outsider need (looking to my image) first an horizontal space, then the inside panel, then another horizontal space. I proceed to add them.

// create an horizontal space of 20px
outside.add(Box.createHorizontalStrut(20));
outside.add(inside);
outside.add(Box.createHorizontalStrut(20));

Now we move to the inside, we need a large white space, the label, another white, a button, a little white, the button, little white, third button and a large white. I proceed to fill inside panel with this.

// create a vertical space of 20px
inside.add(Box.createVerticalStrut(20));

JLabel title = new JLabel("THE TITLE");
inside.add(title);

inside.add(Box.createVerticalStrut(20);

JButton btt1 = new JButton("BUTTON ONE");
// create a new dimension object
Dimension d = new Dimension(200,40);
// set the four kind of size, the button CANNOT be different than the dimension I choose
btt1.setSize(d);
btt1.setMinimumSize(d);
btt1.setMaximumSize(d);
btt1.setPreferredSize(d);
JButton btt2 = new JButton("BUTTON TWO");
btt2.setSize(d);
btt2.setMinimumSize(d);
btt2.setMaximumSize(d);
btt2.setPreferredSize(d);
JButton btt3 = new JButton("BUTTON THREE");
btt3.setSize(d);
btt3.setMinimumSize(d);
btt3.setMaximumSize(d);
btt3.setPreferredSize(d);

// Now that the button are ready we put them in the panel.
inside.add(btt1);
inside.add(Box.createVerticalStrut(5));
inside.add(btt2);
inside.add(box.createVerticalStrut(5));
inside.add(btt3);

// Last white space, the bottom margin:
inside.add(Box.createVerticalStrut(20));

Now I have my structure perfectly set up. Just make it visible and all it's done. Of course you need to put it in a JFrame or a JDialog and of course the first panel can be the JFrame or the JDialog because BoxLayout can be set for any Component.

With this basic tutorial I hope you understood the basics of programming this kind of structures. But you will need to read this in order to go on and make things more complicated: http://docs.oracle.com/javase/tutorial/uiswing/layout/index.html http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html

have a nice day.

Gianmarco
  • 2,536
  • 25
  • 57
  • Thanks for that detailed feedback I will start trying this new construct immediately. Seems very solid. – Dylan Oct 11 '12 at 20:52
  • 2
    I try to do my best, Happy to be useful to you ;) remember to check as preferred answer if you think it is, just under the vote arrows ;) – Gianmarco Oct 11 '12 at 20:58
4

Layouts are incredibly powerful and time saving...Having come from other languages like Delphi and VB, I can tell you one of the best features of Swing are the layout managers.

enter image description here

public class TestLayout06 {

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

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

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MenuPanel());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }            
        });
    }

    protected class MenuPanel extends JPanel {

        public MenuPanel() {            
            JLabel label = new JLabel("Menu");
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(label, gbc);

            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.gridy++;
            add(new JButton("Option 1"), gbc);
            gbc.gridy++;
            add(new JButton("Option 2"), gbc);
            gbc.gridy++;
            add(new JButton("Option 3"), gbc);
        }
    }
}

Take a look at

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Ok I like the way that looks thanks for the advice. I will read over those 2 learning guides immediately thanks – Dylan Oct 11 '12 at 20:57