Domanda

I want to create a custom JPanel to allow my user to select one of 4 corners. I have done this by using 4 JRadioButtons and placing a TitledBorder on the panel.

I would like the panel to always be as small as possible for a neat and clean look to the panel. I thought this was possible since layouts are supposed to respect the Maximum and Minimum size properties.

First I tried setting them to the minimum size using setMaximumSize() and setPreferredSize() but that did not work. Then I tried overloading getMaximumSize() and getPreferredSize() but that seemed to have no effect either. In all my layouts my panel grows to fill the space dictated by the layout on which it is placed. I've tested on a GridBagLayout where I want to place it and on a BorderLayout in a otherwise empty JFrame created for testing.

Here is my code:

public class OverlayAnchorPanel extends JPanel implements ItemListener{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private AnchorChangeListener anchorListener;
    private JRadioButton rdbtnSouthEast;
    private JRadioButton rdbtnSouthWest;
    private JRadioButton rdbtnNorthWest;
    private JRadioButton rdbtnNorthEast;
    private ButtonGroup radioGroup;

    /**
     * Create the panel.
     */
    public OverlayAnchorPanel() {
        this.radioGroup = new ButtonGroup();
        setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Anchor", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[]{0, 0};
        gridBagLayout.rowHeights = new int[]{0, 0};
        gridBagLayout.columnWeights = new double[]{0.0, 0.0};
        gridBagLayout.rowWeights = new double[]{0.0, 0.0};
        setLayout(gridBagLayout);

        rdbtnNorthEast = new JRadioButton("");
        GridBagConstraints gbc_rdbtnNorthEast = new GridBagConstraints();
        gbc_rdbtnNorthEast.insets = new Insets(0, 0, 5, 0);
        gbc_rdbtnNorthEast.gridx = 1;
        gbc_rdbtnNorthEast.gridy = 0;
        add(rdbtnNorthEast, gbc_rdbtnNorthEast);
        this.radioGroup.add(rdbtnNorthEast);

        rdbtnNorthWest = new JRadioButton("");
        GridBagConstraints gbc_rdbtnNorthWest = new GridBagConstraints();
        gbc_rdbtnNorthWest.insets = new Insets(0, 0, 5, 5);
        gbc_rdbtnNorthWest.gridx = 0;
        gbc_rdbtnNorthWest.gridy = 0;
        add(rdbtnNorthWest, gbc_rdbtnNorthWest);
        this.radioGroup.add(rdbtnNorthWest);

        rdbtnSouthWest = new JRadioButton("");
        GridBagConstraints gbc_rdbtnSouthWest = new GridBagConstraints();
        gbc_rdbtnSouthWest.insets = new Insets(0, 0, 0, 5);
        gbc_rdbtnSouthWest.gridx = 0;
        gbc_rdbtnSouthWest.gridy = 1;
        add(rdbtnSouthWest, gbc_rdbtnSouthWest);
        this.radioGroup.add(rdbtnSouthWest);

        rdbtnSouthEast = new JRadioButton("");
        rdbtnSouthEast.setSelected(true);
        GridBagConstraints gbc_rdbtnSouthEast = new GridBagConstraints();
        gbc_rdbtnSouthEast.gridx = 1;
        gbc_rdbtnSouthEast.gridy = 1;
        add(rdbtnSouthEast, gbc_rdbtnSouthEast);;
        this.radioGroup.add(rdbtnSouthEast);

        // This was my first attempt and did not work
        //this.setMaximumSize(this.getMinimumSize());
        //this.setPreferredSize(this.getMinimumSize());
    }

    public AnchorChangeListener getAnchorListener() {
        return anchorListener;
    }

    public void setAnchorListener(AnchorChangeListener anchorListener) {
        this.anchorListener = anchorListener;
    }


    @Override
    public void itemStateChanged(ItemEvent arg0) {
        OverlayAnchor newAnchor;
        if(arg0.getSource() == this.rdbtnNorthEast){
            newAnchor = OverlayAnchor.NORTHEAST;
        } else if(arg0.getSource() == this.rdbtnNorthWest){
            newAnchor = OverlayAnchor.NORTHWEST;
        } else if(arg0.getSource() == this.rdbtnSouthEast){
            newAnchor = OverlayAnchor.SOUTHEAST;
        } else{
            newAnchor = OverlayAnchor.SOUTHWEST;
        }
        if(this.anchorListener !=null){
            this.anchorListener.anchorChanged(new AnchorChangeEvent(this, newAnchor));
        }
    }

    public Dimension getPreferredSize(){
        return this.getMinimumSize();
    }

    public Dimension getMaximumSize(){
        return this.getMinimumSize();
    }
}
È stato utile?

Soluzione 2

In order to achieve the result desired of a self contained custom component that does not change in size I had to wrap it in another panel that will change in size but lays itself out in a manor that will respect the preferred size of my panel.

Here is my final code:

public class OverlayAnchorPanel extends JPanel implements ItemListener {
    private static final long serialVersionUID = 1L;

    private AnchorChangeListener anchorListener;
    private JRadioButton rdbtnSouthEast;
    private JRadioButton rdbtnSouthWest;
    private JRadioButton rdbtnNorthWest;
    private JRadioButton rdbtnNorthEast;
    private ButtonGroup radioGroup;
    private JPanel panel;

    /**
     * Create the panel.
     */
    public OverlayAnchorPanel() {
        this.radioGroup = new ButtonGroup();;
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[] {0};
        gridBagLayout.rowHeights = new int[] {0};
        gridBagLayout.columnWeights = new double[]{0.0};
        gridBagLayout.rowWeights = new double[]{0.0};
        setLayout(gridBagLayout);

        panel = new JPanel();
        panel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Anchor", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        GridBagConstraints gbc_panel = new GridBagConstraints();
        gbc_panel.anchor = GridBagConstraints.NORTHWEST;
        gbc_panel.gridx = 0;
        gbc_panel.gridy = 0;
        add(panel, gbc_panel);
        GridBagLayout gbl_panel = new GridBagLayout();
        gbl_panel.columnWidths = new int[] {0, 0};
        gbl_panel.rowHeights = new int[] {0, 0};
        gbl_panel.columnWeights = new double[]{0.0, 0.0};
        gbl_panel.rowWeights = new double[]{0.0, 0.0};
        panel.setLayout(gbl_panel);

        rdbtnNorthEast = new JRadioButton("");
        GridBagConstraints gbc_rdbtnNorthEast = new GridBagConstraints();
        gbc_rdbtnNorthEast.fill = GridBagConstraints.BOTH;
        gbc_rdbtnNorthEast.insets = new Insets(0, 0, 5, 5);
        gbc_rdbtnNorthEast.gridx = 0;
        gbc_rdbtnNorthEast.gridy = 0;
        panel.add(rdbtnNorthEast, gbc_rdbtnNorthEast);
        this.radioGroup.add(rdbtnNorthEast);

        rdbtnNorthWest = new JRadioButton("");
        GridBagConstraints gbc_rdbtnNorthWest = new GridBagConstraints();
        gbc_rdbtnNorthWest.fill = GridBagConstraints.BOTH;
        gbc_rdbtnNorthWest.insets = new Insets(0, 0, 5, 0);
        gbc_rdbtnNorthWest.gridx = 1;
        gbc_rdbtnNorthWest.gridy = 0;
        panel.add(rdbtnNorthWest, gbc_rdbtnNorthWest);
        this.radioGroup.add(rdbtnNorthWest);

        rdbtnSouthWest = new JRadioButton("");
        GridBagConstraints gbc_rdbtnSouthWest = new GridBagConstraints();
        gbc_rdbtnSouthWest.fill = GridBagConstraints.BOTH;
        gbc_rdbtnSouthWest.insets = new Insets(0, 0, 0, 5);
        gbc_rdbtnSouthWest.gridx = 0;
        gbc_rdbtnSouthWest.gridy = 1;
        panel.add(rdbtnSouthWest, gbc_rdbtnSouthWest);
        this.radioGroup.add(rdbtnSouthWest);

        rdbtnSouthEast = new JRadioButton("");
        GridBagConstraints gbc_rdbtnSouthEast = new GridBagConstraints();
        gbc_rdbtnSouthEast.fill = GridBagConstraints.BOTH;
        gbc_rdbtnSouthEast.gridx = 1;
        gbc_rdbtnSouthEast.gridy = 1;
        panel.add(rdbtnSouthEast, gbc_rdbtnSouthEast);
        rdbtnSouthEast.setSelected(true);
        this.radioGroup.add(rdbtnSouthEast);
    }

    public AnchorChangeListener getAnchorListener() {
        return anchorListener;
    }

    public void setAnchorListener(AnchorChangeListener anchorListener) {
        this.anchorListener = anchorListener;
    }


    @Override
    public void itemStateChanged(ItemEvent arg0) {
        OverlayAnchor newAnchor;
        if(arg0.getSource() == this.rdbtnNorthEast){
            newAnchor = OverlayAnchor.NORTHEAST;
        } else if(arg0.getSource() == this.rdbtnNorthWest) {
            newAnchor = OverlayAnchor.NORTHWEST;
        } else if(arg0.getSource() == this.rdbtnSouthEast) {
            newAnchor = OverlayAnchor.SOUTHEAST;
        } else {
            newAnchor = OverlayAnchor.SOUTHWEST;
        }
        if(this.anchorListener !=null) {
            this.anchorListener.anchorChanged(new AnchorChangeEvent(this, newAnchor));
        }
    }

    public Dimension getPreferredSize() {
        return this.getMinimumSize();
    }

    public Dimension getMaximumSize() {
        return this.getMinimumSize();
    }
}

Altri suggerimenti

How a component is laid out comes down to a number of things. The first is, obviously, the choice of layout manager for the parent container.

A layout manager is free to use the information from getPreferred/Miniumum/MaximumSize it is also free to ignore them or use combinations of them as it wants.

For example, BorderLayout tends to use the preferred size of the components, but will allow the parent container to expand and shrink as it likes, generally expanding and shrinking the CENTER component as required.

In my testing, I simply changed the layout manager of the frame to GridBagLayout and got this result...

Anchor

Basically, GridBagLayout will honor the size hints so long as they don't contradict the constraints you provide it.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top