My Problem is, that I want to have a my Buttons in the SOUTH in a
Border Layout.
There, the buttons are aligned in a FlowLayout. When the user
changes the size of the Window, the buttons are repainted.
If there is not enough space, the Buttons disapear, instead of what
I want to have:
The SOUTH region enlarges and two rows of buttons appear.
Any Idea how to perform the above task?
Here the source I use to test the behaviour:
-----
import java.awt.*;
import javax.swing.*;
public class MultiLineSouth {
public static void main(String[] args) {
new MultiLineSouth().top();
}
void top() {
JFrame jf = new JFrame("Multiple Lines in the South");
JPanel mainPanel = makeMainPanel();
jf.add(mainPanel);
jf.setSize(300, 300);
jf.setVisible(true);
}
JPanel makeMainPanel() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
populateMainPanel(mainPanel);
return mainPanel;
}
void populateMainPanel(JPanel mainPanel) {
JLabel centerLabel = new JLabel("center");
mainPanel.add(centerLabel, BorderLayout.CENTER);
JPanel southPanel = makeSouthPanel();
mainPanel.add(southPanel, BorderLayout.SOUTH);
}
JPanel makeSouthPanel() {
JPanel southPanel = new JPanel();
//southPanel.setLayout(null); // which to use here?
populateSouthPanel(southPanel);
return southPanel;
}
void populateSouthPanel(JPanel southPanel) {
JPanel mehrZeilenPanel = makeMultiLinePanel();
southPanel.add(mehrZeilenPanel);
}
JPanel makeMultiLinePanel() {
JPanel mzp = new JPanel();
mzp.setLayout(new FlowLayout());
populateMultiLinePanel(mzp);
return mzp;
}
void populateMultiLinePanel(JPanel mzp) {
mzp.add(new JButton("Hello"));
mzp.add(new JButton("World"));
mzp.add(new JButton("OK"));
mzp.add(new JButton("Cancel"));
}
} // end of class MultiLineSouth
-----
thx
> My Problem is, that I want to have a my Buttons in the SOUTH in a
> BorderLayout. There, the buttons are aligned in a FlowLayout. When
> the user changes the size of the Window, the buttons are repainted.
> If there is not enough space, the Buttons disapear, instead of what I
> want to have: The SOUTH region enlarges and two rows of buttons
> appear.
>
> Any Idea how to perform the above task?
Here's one approach using BoxLayout instead of BorderLayout. You may
want to look into using filler instead of glue:
<http://java.sun.com/docs/books/tutorial/uiswing/layout/box.html>
import java.awt.*;
import javax.swing.*;
public class MultiLineSouth implements Runnable {
public static void main(String[] args) {
EventQueue.invokeLater(new MultiLineSouth());
}
@Override
public void run() {
JFrame jf = new JFrame("Multiple Lines in the South");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(makeMainPanel());
jf.pack();
jf.setVisible(true);
}
JPanel makeMainPanel() {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(new JLabel("top"));
panel.add(Box.createVerticalGlue());
panel.add(new JLabel("center"));
panel.add(Box.createVerticalGlue());
panel.add(makeSouthPanel());
return panel;
}
JPanel makeSouthPanel() {
JPanel panel = new JPanel(); // Default FlowLayout
panel.add(new JButton("Hello"));
panel.add(new JButton("World"));
panel.add(new JButton("OK"));
panel.add(new JButton("Cancel"));
return panel;
}
}
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
If you read the Java doc for BorderLayout, it says something about
constraints placed on the NORTH, SOUTH, EAST and WEST containers. It's
not clear to me what that means, but at a guess I'd say that the
constraint means that the JPanel you added isn't allowed to increase
it's size vertically, so it's constrained to only displaying one row.
As John said I think this is a good place to roll your own layout.
Unfortunately, I think BoxLayout might be too simplistic for what you
really want to do. You might look into a GUI layout tool, like Matisse,
which comes with NetBeans, which will make it easier to use a more
complicated layout like Sprint or Group.
> phi wrote:
> > My Problem is, that I want to have a my Buttons in the SOUTH in a
> > Border Layout.
> > There, the buttons are aligned in a FlowLayout. When the user
> > changes the size of the Window, the buttons are repainted. If there
> > is not enough space, the Buttons disapear, instead of what I want
> > to have:
>
>
> If you read the Java doc for BorderLayout, it says something about
> constraints placed on the NORTH, SOUTH, EAST and WEST containers.
> It's not clear to me what that means, but at a guess I'd say that the
> constraint means that the JPanel you added isn't allowed to increase
> it's size vertically, so it's constrained to only displaying one row.
>
> As John said I think this is a good place to roll your own layout.
I can't take the credit, but this is good advice.
> Unfortunately, I think BoxLayout might be too simplistic for what you
> really want to do.
Conversely, adding the buttons to a JToolBar may obviate the need to
line-wrap the panel at all.
<http://java.sun.com/javase/6/docs/api/javax/swing/JToolBar.html>
> You might look into a GUI layout tool, like Matisse, which comes with
> NetBeans, which will make it easier to use a more complicated layout
> like Spring or Group.
I looked at this some more. I don't think FlowLayout returns a good
result for BorderLayout, at least for the outer panels. Problem is,
FlowLayout, if you look at the code, only calculates a preferred size
which does not take into account the width of the parent container. The
preferred size of a FlowLayout is always a single row.
This is kinda weird, and not what BorderLayout is really expecting. So
I adapted a new preferredSize method from the actual layoutContainer
code. It seems to work.
This code below is pasted from my IDE, then edited a bit. I hope it all
still compiles. If not, post and ask me for the whole thing (which is
rather messy).
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;
import java.awt.*;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
/**
*
* @author Brenden
*/
public class TestLayout
{
public static void main( String[] args )
{
SwingUtilities.invokeLater( new Runnable()
{
public void run()
{
buildAndShowGui();
}
} );
}
private static void buildAndShowGui()
{
top();
}
static void top()
{
JFrame jf = new JFrame( "Multiple Lines in the South" );
jf.add( new JLabel( "center" ) );
// JPanel mainPanel = makeMainPanel();
// jf.add(mainPanel);
jf.add( makeSouthPanel(), BorderLayout.SOUTH );
jf.setSize( 300, 300 );
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jf.setVisible( true );
}
static JPanel makeMainPanel()
{
JPanel mainPanel = new JPanel();
mainPanel.setLayout( new BorderLayout() );
populateMainPanel( mainPanel );
return mainPanel;
}
static JPanel makeSouthPanel()
{
JPanel southPanel = new JPanel();
southPanel.setLayout( new LayoutInspector() );
//southPanel.setLayout(null); // which to use here?
populateMultiLinePanel( southPanel );
return southPanel;
}
static JPanel makeMultiLinePanel()
{
JPanel mzp = new JPanel();
mzp.setLayout( new LayoutInspector() );
populateMultiLinePanel( mzp );
return mzp;
}
static void populateMultiLinePanel( Container mzp )
{
mzp.add( new JButton( "Hello" ) );
mzp.add( new JButton( "World" ) );
mzp.add( new JButton( "OK" ) );
mzp.add( new JButton( "Cancel" ) );
}
}
class LayoutInspector
extends FlowLayout
{
private static Logger log =
Logger.getAnonymousLogger();
static
{
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel( Level.ALL );
log.addHandler( ch );
log.setLevel( Level.ALL );
log.setUseParentHandlers( false );
}
public void addLayoutComponent( String name, Component comp )
{
log.entering( "FlowLayout", "addLayoutComponent",
new Object[]
{
name, comp
} );
// throw new UnsupportedOperationException( "Not supported yet." );
super.addLayoutComponent( name, comp );
log.exiting( "FlowLayout", "addLayoutComponent" );
}
public void removeLayoutComponent( Component comp )
{
log.entering( "FlowLayout", "removeLayoutComponent",
new Object[]
{
comp
} );
// throw new UnsupportedOperationException( "Not supported yet." );
super.removeLayoutComponent( comp );
log.exiting( "FlowLayout", "removeLayoutComponent" );
throw new UnsupportedOperationException( "Not supported yet." );
}
public Dimension preferredLayoutSize( Container parent )
{
log.entering( "FlowLayout", "preferredLayoutSize",
new Object[] { parent } );
// throw new UnsupportedOperationException( "Not supported yet." );
// Dimension rt =
// super.preferredLayoutSize( parent );
// log.finest( "Dimenions="+rt);
Insets insets = parent.getInsets();
int maxwidth = parent.getWidth() - (insets.left + insets.right +
super.getHgap() * 2);
int ourMaxwidth = 0;
int nmembers = parent.getComponentCount();
int x = 0, y = insets.top + super.getVgap();
int rowh = 0, start = 0;
boolean ltr = parent.getComponentOrientation().isLeftToRight();
boolean useBaseline = getAlignOnBaseline();
int[] ascent = null;
int[] descent = null;
if( useBaseline )
{
ascent = new int[nmembers];
descent = new int[nmembers];
}
for( int i = 0; i < nmembers; i++ )
{
Component m = parent.getComponent( i );
if( m.isVisible() )
{
Dimension d = m.getPreferredSize();
m.setSize( d.width, d.height );
if( useBaseline )
{
int baseline = m.getBaseline( d.width, d.height );
if( baseline >= 0 )
{
ascent[i] = baseline;
descent[i] = d.height - baseline;
} else
{
ascent[i] = -1;
}
}
if( (x == 0) || ((x + d.width) <= maxwidth) )
{
if( x > 0 )
{
x += super.getHgap();
}
x += d.width;
rowh = Math.max( rowh, d.height );
} else
{
// rowh = moveComponents( parent, insets.left + hgap, y,
// maxwidth - x, rowh, start, i, ltr,
// useBaseline, ascent, descent );
ourMaxwidth = Math.max( ourMaxwidth, x );
x = d.width;
y += super.getVgap() + rowh;
rowh = d.height;
start = i;
}
}
}
// moveComponents( parent, insets.left + hgap, y, maxwidth - x, //rowh,
// start, nmembers, ltr, useBaseline, ascent, descent );
ourMaxwidth = Math.max( ourMaxwidth, x );
Dimension rt = new Dimension( ourMaxwidth, y+rowh );
log.finest( "Dimenions="+rt);
log.exiting( "FlowLayout", "preferredLayoutSize" );
return rt;
}
public Dimension minimumLayoutSize( Container parent )
{
log.entering( "FlowLayout", "minimumLayoutSize",
new Object[]
{
parent
} );
// throw new UnsupportedOperationException( "Not supported yet." );
Dimension rt =
super.minimumLayoutSize( parent );
log.finest( "Dimenions=" + rt );
log.exiting( "FlowLayout", "minimumLayoutSize" );
return rt;
}
public void layoutContainer( Container parent )
{
log.entering( "FlowLayout", "layoutContainer",
new Object[]
{
parent
} );
// throw new UnsupportedOperationException( "Not supported yet." );
super.layoutContainer( parent );
log.exiting( "FlowLayout", "layoutContainer" );
}
}