How to align swing buttons vertically ?

O

Olivier Scalbert

Hello !

I want to create a swing application with a main frame and a panel
containing vertically aligned buttons at the right side. Here is the code:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
});
}
}

class ViewerFrame extends JFrame {

public ViewerFrame() {
getContentPane().add(new JPanel(), BorderLayout.CENTER);
getContentPane().add(createBtnPanel(), BorderLayout.EAST);
}

private JPanel createBtnPanel() {
JPanel btnPanel = new JPanel();

btnPanel.setLayout(new GridLayout(0, 1));

btnPanel.add(new JButton("Button 1"));
btnPanel.add(new JButton("Button 2"));
btnPanel.add(new JButton("Long Button 3"));
btnPanel.add(new JButton("Button 4"));
btnPanel.add(new JButton("Button 5"));

// Trick here !
// I put the btnPanel at the NORTH of a "dummy" panel to have
// the correct button sizes !!!
// Other solutions ??
JPanel dummyPanel = new JPanel();
dummyPanel.setLayout(new BorderLayout());
dummyPanel.add(btnPanel, BorderLayout.NORTH);

return dummyPanel;
}
}

It works, but is there an other way to avoid the dummyPanel trick ?

Thanks a lot !

Olivier
 
M

Martin Gregorie

Thanks !
But with the BoxLayout they are aligned but they have not the same size!
That's nothing to do with the layout. It aligns the objects you're laying
out by doing its best with the sizes of the objects you created.

JButton inherits size setting methods (setMaximumSize, setMinimumSize,
setPreferredSize) from JComponent. Use them to control button size.
 
R

Roedy Green

I want to create a swing application with a main frame and a panel
containing vertically aligned buttons at the right side. Here is the code:

How Components align is decided by the Layout Manager. It might take
clues from fields in the Components, or it may not. Usually when you
start having trouble intimidating your LayoutManager into ever higher
levels of aesthetic perfection, it is time for a more advanced
LayoutManager, or cannibalising ideas from other users of your current
LayoutManager. It is amazing how much source code you can find with
Google with some package, class or method names.


See http://mindprod.com/jgloss/layout.html
 
O

Olivier Scalbert

That's nothing to do with the layout. It aligns the objects you're laying
out by doing its best with the sizes of the objects you created.

JButton inherits size setting methods (setMaximumSize, setMinimumSize,
setPreferredSize) from JComponent. Use them to control button size.

Perhaps I have not understand, but with the following code, buttons are
not well aligned:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
});
}
}

class ViewerFrame extends JFrame {

public ViewerFrame() {
getContentPane().add(new JPanel(), BorderLayout.CENTER);
getContentPane().add(createBtnPanel(), BorderLayout.EAST);
}

private JPanel createBtnPanel() {
JPanel btnPanel = new JPanel();

btnPanel.setLayout(new BoxLayout(btnPanel, BoxLayout.Y_AXIS));

btnPanel.add(new JButton("Button 1"));
btnPanel.add(new JButton("Button 2"));
btnPanel.add(new JButton("Long Button 3"));
btnPanel.add(new JButton("Button 4"));
btnPanel.add(new JButton("Button 5"));

return btnPanel;
}
}

Olivier
 
K

Knute Johnson

That's nothing to do with the layout. It aligns the objects you're laying
out by doing its best with the sizes of the objects you created.

JButton inherits size setting methods (setMaximumSize, setMinimumSize,
setPreferredSize) from JComponent. Use them to control button size.

Perhaps I have not understand, but with the following code, buttons are
not well aligned:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
});
}
}

class ViewerFrame extends JFrame {

public ViewerFrame() {
getContentPane().add(new JPanel(), BorderLayout.CENTER);
getContentPane().add(createBtnPanel(), BorderLayout.EAST);
}

private JPanel createBtnPanel() {
JPanel btnPanel = new JPanel();

btnPanel.setLayout(new BoxLayout(btnPanel, BoxLayout.Y_AXIS));

btnPanel.add(new JButton("Button 1"));
btnPanel.add(new JButton("Button 2"));
btnPanel.add(new JButton("Long Button 3"));
btnPanel.add(new JButton("Button 4"));
btnPanel.add(new JButton("Button 5"));

return btnPanel;
}
}

Olivier

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test extends JPanel {
public test() {
super(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;

String labels[] = {"Button 1","Button 2",
"Long Button 3","Button 4","Button 5"};

for (int i=0; i<labels.length; i++) {
add(new JButton(labels),c);
++c.gridy;
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new test(),BorderLayout.EAST);
f.setSize(700,500);
f.setVisible(true);
}
});
}
}
 
L

Lew

Olivier said:
Perhaps I have not understand, but with the following code, buttons are
not well aligned:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);

Shouldn't you call 'pack()' right here? Layouts often don't work well without it.
 
M

Martin Gregorie

Perhaps I have not understand, but with the following code, buttons are
not well aligned:
They aligned as I'd expect:
- btnPanel is sized to contain the buttons and nothing else
and is placed as you asked, on the east side of the content pane.

- The buttons have their centres aligned.

I don't understand what you mean by "not well aligned":

- If you want the buttons to appear as other than a close-packed block,
take a look at "How to use BoxLayout" in the Java tutorial. It is also
referenced from the the class description in the BoxLayout javadocs
entry.

- If you want all buttons to be the same size, use a custom class in
place of JButton:

import java.awt.*;
import javax.swing.*;

class MyButton extends JButton
{

public MyButton(String label)
{
super(label);

Dimension d = new Dimension(120, 30);
setMinimumSize(d);
setMaximumSize(d);
setPreferredSize(d);
}
}
 
O

Olivier Scalbert

They aligned as I'd expect:
- btnPanel is sized to contain the buttons and nothing else
and is placed as you asked, on the east side of the content pane.

- The buttons have their centres aligned.

I don't understand what you mean by "not well aligned":

- If you want the buttons to appear as other than a close-packed block,
take a look at "How to use BoxLayout" in the Java tutorial. It is also
referenced from the the class description in the BoxLayout javadocs
entry.

- If you want all buttons to be the same size, use a custom class in
place of JButton:

import java.awt.*;
import javax.swing.*;

class MyButton extends JButton
{

public MyButton(String label)
{
super(label);

Dimension d = new Dimension(120, 30);
setMinimumSize(d);
setMaximumSize(d);
setPreferredSize(d);
}
}

Hi,

With "my version", I have (at least on my machine):
 
O

Olivier Scalbert

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test extends JPanel {
public test() {
super(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;

String labels[] = {"Button 1","Button 2",
"Long Button 3","Button 4","Button 5"};

for (int i=0; i<labels.length; i++) {
add(new JButton(labels),c);
++c.gridy;
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new test(),BorderLayout.EAST);
f.setSize(700,500);
f.setVisible(true);
}
});
}
}

Ok, all the buttons have the same size and are aligned ! When I resize
the main frame, the group of buttons is in the EAST part but in the
middle of the frame height. Is it possible the have this group on top
(of the EAST part) ?
 
J

John B. Matthews

Olivier Scalbert said:
With "my version", I have (at least on my machine):
-----------------
| button 1 |
-----------------
| button 2 |
-----------------
| Long Button 3 |
-----------------
| button 4 |

Lew is correct about using pack(), and I'm with Martin on BoxLayout.
One problem with using setXXXSize is that the values statically replace
those computed by the component's Look & Feel. Instead override just
the one needed by BoxLayout to make the buttons "as wide as their
container."

<http://download.oracle.com/javase/tutorial/uiswing/layout/box.html>

As an aside, your center panel contains no components, so it would
pack() to the L&F's minimum. I've given it an arbitrary size by
overriding getPreferredSize(), but setPreferredSize() would do as well
for the fixed value.

I defer to Knute on GridBagLayout.

Here's an <http://sscce.org/>:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

class ViewerFrame extends JFrame {

public ViewerFrame() {
// a panel of aribtrary size
this.add(new JPanel() {

@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}, BorderLayout.CENTER);
this.add(createBtnPanel(), BorderLayout.EAST);
}

private JPanel createBtnPanel() {
JPanel btnPanel = new JPanel();
btnPanel.setLayout(new BoxLayout(btnPanel, BoxLayout.Y_AXIS));
btnPanel.add(createButton("Button 1"));
btnPanel.add(createButton("Button 2"));
btnPanel.add(createButton("Long Button 3"));
btnPanel.add(createButton("Button 4"));
btnPanel.add(createButton("Button 5"));
return btnPanel;
}

private JButton createButton(String name) {
final JButton b = new JButton(name) {

@Override
public Dimension getMaximumSize() {
return new Dimension(
Short.MAX_VALUE, getPreferredSize().height);
}
};
b.setAlignmentX(0.5f);
return b;
}
}
 
K

Knute Johnson

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test extends JPanel {
public test() {
super(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;

String labels[] = {"Button 1","Button 2",
"Long Button 3","Button 4","Button 5"};

for (int i=0; i<labels.length; i++) {

if (i == labels.length - 1) { // last label
// anchor last button to north and give it
// a weighty of 1.0. this will tell that
// button to take all remaining vertical
// space and will push all the other
// buttons to top of the container
c.anchor = GridBagConstraints.NORTH;
c.weighty = 1.0
}
add(new JButton(labels),c);
++c.gridy;
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new test(),BorderLayout.EAST);
f.setSize(700,500);
f.setVisible(true);
}
});
}
}

Ok, all the buttons have the same size and are aligned ! When I resize
the main frame, the group of buttons is in the EAST part but in the
middle of the frame height. Is it possible the have this group on top
(of the EAST part) ?
 
K

Knute Johnson

Olivier said:
Perhaps I have not understand, but with the following code, buttons are
not well aligned:

import java.awt.*;
import javax.swing.*;

public class TestViewer {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);

Shouldn't you call 'pack()' right here? Layouts often don't work well without it.

The OP created a pretty good SSCCE here and for that purpose pack()
would not demonstrate what he wanted to show. The only possible problem
he would have with the LayoutManager is too little space to display his
example. Most of the time, having extra space in a frame isn't going to
cause any display problems. I think he can be forgiven for not packing
this time (as I hope I can for my example :).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top