3

Can anyone help with this problem I'm trying to create a JToolBar and I want all its components to be fixed in size and position. I've tried a few different layout managers but they all center and/or re-size the components when the frame it's in is re-sized.

Here is an example using GridbagLayout, I have also used the default layout manager using the toolbar.add(component) method but the result is the same : '

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;

public class ToolBarTest extends JFrame
{
    private JToolBar toolbar;
    private JPanel mainPanel;
    private JPanel toolBarPanel;
    private JButton aButton;
    private JCheckBox aCheckBox;
    private JList aList;
    private Box toolbarBox;
    private GridBagConstraints toolbarConstraints;
    private GridBagLayout toolbarLayout;
    private JLabel shapeLabel;
    private JComboBox<ImageIcon> shapeChooser;
    private JLabel colorLabel;
    private JComboBox colorChooser;

    private String colorNames[] = { "Black" , "Blue", "Cyan", "Dark Gray",
            "Gray", "Green", "Light Gray", "Magenta", "Orange",
            "Pink", "Red", "White", "Yellow", "Custom" };

    private String shapeNames[] = { "Line", "Oval", "Rectangle",
        "3D Rectangle","Paint Brush", "Rounded Rectangle" };

    public ToolBarTest()
    {


        setLayout( new BorderLayout() );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        setSize( 500, 500 );


        add( createToolBar(), BorderLayout.PAGE_START );

        setVisible( true );

    }


    public void addToToolbar( Component component, int row, int column )
    {
        toolbarConstraints.gridx = column;
        toolbarConstraints.gridy = row;
        toolbarConstraints.anchor = GridBagConstraints.WEST;
        toolbarConstraints.fill = GridBagConstraints.NONE;
        toolbarConstraints.weightx = 0;
        toolbarConstraints.weighty = 0;
        toolbarConstraints.gridwidth = 1;
        toolbarConstraints.gridheight = 1;
        toolbarLayout.setConstraints( component, toolbarConstraints );
        toolbar.add( component );

    }// end addToToolbar


    public final JToolBar createToolBar()
    {
        toolbarLayout = new GridBagLayout();
        toolbarConstraints = new GridBagConstraints();

        // create the tool bar which holds the items to draw
        toolbar = new JToolBar();
        toolbar.setBorderPainted(true);
        toolbar.setLayout( toolbarLayout );
        toolbar.setFloatable( true );




        shapeLabel = new JLabel( "Shapes: " );
        addToToolbar( shapeLabel, 0, 1 );


        String iconNames[] = { "PaintImages/Line.jpg", 
            "PaintImages/Oval.jpg", "PaintImages/Rect.jpg",
            "PaintImages/3DRect.jpg","PaintImages/PaintBrush.jpg",
        "PaintImages/RoundRect.jpg"};

        ImageIcon shapeIcons[] = new ImageIcon[ shapeNames.length ];


        // create image icons 
        for( int shapeButton = 0; shapeButton < shapeNames.length; shapeButton++ )
        {

            shapeIcons[ shapeButton ] =
                    new ImageIcon( iconNames[ shapeButton ] );

        }// end for


        shapeChooser = 
                new JComboBox< ImageIcon >( shapeIcons );

        shapeChooser.setSize(  new Dimension( 50, 20 ));

        shapeChooser.setPrototypeDisplayValue( shapeIcons[ 0 ] ); 

        shapeChooser.setSelectedIndex( 0 );

        addToToolbar( shapeChooser, 0, 2 );

        colorLabel = new JLabel( "Colors: " );

        addToToolbar( colorLabel, 0, 3 );

        colorChooser = new JComboBox( colorNames );
        addToToolbar( colorChooser, 0, 4 );


        return toolbar;
    }// end createToolBar

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

    }// end main


}// end class ToolBarTest'
Frederic
  • 2,015
  • 4
  • 20
  • 37
S1.Mac
  • 33
  • 1
  • 5
  • I think that similair question was asked last month – mKorbel Nov 12 '12 at 14:42
  • 4
    _they all center and/or re-size the components_ that's unusual, particularly for the default which is a specialized BoxLayout ;-) show us what you tried - as an SSCCE (google the abbreviation if you don't know it) – kleopatra Nov 12 '12 at 14:47
  • 1
    *"Can anyone help with this problem i'm trying to create a JToolBar and I want all its components to be fixed in size and position."* An easy (and obvious) fix is "Don't do that, let each component assume the natural size (with a couple of exceptions - e.g. `JComboBox`)". – Andrew Thompson Nov 12 '12 at 15:05
  • Sorry about that please see revised code – S1.Mac Nov 12 '12 at 15:22
  • @Andrew Thompson i tried just letting them assume their natural size but the last component always fills the remaining area left on the tool bar – S1.Mac Nov 12 '12 at 15:26

2 Answers2

5

As already mentioned: the default Layout of JToolBar is-a BoxLayout which respects a component's maxSize. A JComboBox hasn't a reasonable max, so you need to subclass and override getMaxSize:

protected JComboBox createCombo(Object[] shapeIcons) {
    return new JComboBox( shapeIcons ) {

        @Override
        public Dimension getMaximumSize() {
            return getPreferredSize();
        }

    };
}

// usage (keep the default layoutManager of the toolbar)
shapeChooser = createCombo(shapeIcons);
toolBar.add(shapeChooser);
... 
colorChooser = createCombo( colorNames );
toolBar.add(colorChooser)
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • @mKorbel hmm ... not sure I understand what you are saying: a combo is no reasonable max in _any_ LF, that's the whole point :-) Can't see anything special (except that its pref for empty is wayy too small) – kleopatra Nov 13 '12 at 08:35
1

Here is an alternative to extending the JComboBox. It simply locks the preferred & min/max sizes to the preferred size when added to the tool bar.

ToolBarTest

Another tweak would be to add an EmtpyBorder to any instanceof a JLabel. They seem a bit 'crowded' there.

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

public class ToolBarTest extends JFrame
{
    private JToolBar toolbar;
    private JLabel shapeLabel;
    private JComboBox shapeChooser;
    private JLabel colorLabel;
    private JComboBox colorChooser;

    private String colorNames[] = { "Black" , "Blue", "Cyan", "Dark Gray",
            "Gray", "Green", "Light Gray", "Magenta", "Orange",
            "Pink", "Red", "White", "Yellow", "Custom" };

    private String shapeNames[] = { "Line", "Oval", "Rectangle",
        "3D Rectangle","Paint Brush", "Rounded Rectangle" };

    public ToolBarTest()
    {
        setLayout( new BorderLayout() );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        setSize( 500, 200 );
        add( createToolBar(), BorderLayout.PAGE_START );

        setVisible( true );
    }

    public void addToToolbar( Component component, int row, int column )
    {
        Dimension d = component.getPreferredSize();
        component.setMaximumSize(d);
        component.setMinimumSize(d);
        component.setPreferredSize(d);
        toolbar.add( component );

    }// end addToToolbar

    public final JToolBar createToolBar()
    {
        // create the tool bar which holds the items to draw
        toolbar = new JToolBar();

        shapeLabel = new JLabel( "Shapes: " );
        addToToolbar( shapeLabel, 0, 1 );

        shapeChooser = 
                new JComboBox( shapeNames );
        shapeChooser.setSelectedIndex( 0 );
        addToToolbar( shapeChooser, 0, 2 );
        colorLabel = new JLabel( "Colors: " );

        addToToolbar( colorLabel, 0, 3 );

        colorChooser = new JComboBox( colorNames );
        addToToolbar( colorChooser, 0, 4 );

        return toolbar;
    }// end createToolBar

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

    }// end main
}// end class ToolBarTest'
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • hmm ... going eyes wide open into the downvote? SetXXSize is wrong, always. – kleopatra Nov 13 '12 at 08:30
  • I don't like extending something when we can use the standard version. Note that your example only gets around `set` because it **extends** combo. We are effectively doing the same thing, different ways. So I'm leaving the answer there. -1 if you feel compelled to do so. :) – Andrew Thompson Nov 13 '12 at 08:42
  • 1
    _only gets around set because it extends combo_ yeah, sure - we are indeed changing behaviour (with the default arguable being a bug, so we are bug-hacking :-) The set will break in many cases: if the content changes (add/change items which are wider than the existing, f.i.), change font size, ... anything that will change the pref will not be reflected in the max "lock". Anyway, the real way out would be a LayoutManager that supports a max==pref constraint (not familiar enough with Gridbag, to know if it does similarly to MigLayout) – kleopatra Nov 13 '12 at 09:04
  • @kleopatra Now you put it like that, it is clear that extending combo-box (or using an advanced layout manager) is indeed the better option here. Thanks for the pointers. :) – Andrew Thompson Nov 13 '12 at 09:25
  • Thanks all using the addCombo method sorts out the problem – S1.Mac Nov 13 '12 at 11:58