5

I cannot get BorderLayout to work. I want the cancelbutton to be positioned at the bottom, but it doesn't work. Code:

import java.awt.BorderLayout;

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

import javax.swing.ButtonModel;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

class Test {
    public static JFrame owner;
    public static void main(String[] args) {
        final JDialog frame = new JDialog(owner, "Test");
        frame.setLayout(new BorderLayout());
        frame.setSize(500, 300);
        final JPanel panel = new JPanel();
        final ButtonGroup group = new ButtonGroup();
        String[] options = {"1", "2", "3"};
        for (String text : options) {
            JRadioButton option = new JRadioButton(text);
            option.setActionCommand(text);
            group.add(option);
            panel.add(option);
        }
        JButton okButton = new JButton("OK");
        okButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ButtonModel selectedModel = group.getSelection();
                if (selectedModel != null) {
                    System.err.println(selectedModel.getActionCommand());
                }
            }
        });
        panel.add(okButton);
        JButton cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                frame.dispose();
            }
        });
        panel.add(cancelButton, BorderLayout.SOUTH);
        frame.add(panel);
        frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Tyilo
  • 28,998
  • 40
  • 113
  • 198

3 Answers3

9

You add cancelButton to panel using the BorderLayout.SOUTH constant:

  panel.add(cancelButton, BorderLayout.SOUTH);

But where do you set panel's layout to be BorderLayout? Since you never set this container's layout it will use the default layout for JPanel which is FlowLayout.

Solution: set the panel JPanel's layout to BorderLayout to get BorderLayout behavior.

Once you solve this, you'll have another problem though:

  for (String text : options) {
     JRadioButton option = new JRadioButton(text);
     option.setActionCommand(text);
     group.add(option);
     panel.add(option);
  }

You're adding JRadioButton's to the same panel JPanel without regard to layout. I suspect that you want to add the JRadioButtons to their own JPanel, probably one that uses GridLayout(1, 0) or GridLayout(0, 1), depending on desired orientation, and then that you want to add this JPanel to panel, perhaps in the BorderLayout.CENTER position.

Also you have a similar problem with your okButton in that you add it to panel without regard to layout.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
6

You can try to change

panel.add(cancelButton, BorderLayout.SOUTH);

to

frame.add(cancelButton, BorderLayout.SOUTH);

Result:

enter image description here

user802421
  • 7,465
  • 5
  • 40
  • 63
  • @Tyilo: This is a valid answer, 1+. If this doesn't fulfill your requirements, then you should post an image of what you wants the GUI to look like as user802421 has done. – Hovercraft Full Of Eels Jul 30 '11 at 15:39
  • Love the screen-shot! For some tips on making an even better one, see [How do I create a screenshot to illustrate a post?](http://meta.stackexchange.com/questions/99734/how-do-i-create-a-screenshot-to-illustrate-a-post). – Andrew Thompson Aug 03 '11 at 23:25
3

As Hovercraft Full Of Eels says, JPanel default behavior is the FlowLayout, which is the simplest one, and it's described here. You can easily change it to the manager you need by specifying it inside the constructor:

panel = new JPanel(new BorderLayout())
Jack
  • 131,802
  • 30
  • 241
  • 343
  • -1, since Hovercraft already mention FlowLayout is the default, therer is no need for a duplicate answer. If you want to stress this point you can make a comment in his answer. – camickr Jul 30 '11 at 15:58
  • Actually he didn't state that, he added it as an edit. Should I be precog? :) – Jack Jul 31 '11 at 17:29
  • What?? You start your anwer with "As Hovercraft says...", so the comment was obviously there, If you need more confirmation then click on the link beside the "edited" label and scroll to the bottom where you will find the original posting which was NOT changed with regards to the FlowLayout comment – camickr Jul 31 '11 at 20:47
  • Yes, because I gave a "quick solution solution" snippet to what he told. And I also specified that I wasn't trying to steal anything from anyone.. I mean, there are so many un-polite users there, I always tried to be useful, don't see evil behavior everywhere :/ I'll delete this, if it hurts you. In any case you are right according to Flow Layout, I simply didn't notice it first time I answered.. are you sure that edit tracker tracks also fast edits done just few minutes after first answer? Cause I'm sure it wasn't written there. – Jack Jul 31 '11 at 22:40
  • Again, you say "I gave a quick solution snippet to what he told" which implies that the answer was not edited. The poster already knows how to use a BorderLayout since the second line of code sets the layout. If the main point of your answer was that you can set the layout in the constructor, then that could also have been added as a comment to the original answer. – camickr Jul 31 '11 at 23:27