0

I have a custom button class that I created that extends JButton. When I add this to a JFrame, I get this:

enter image description here

But when I place this custom button into the frame with BoxLayout, the button becomes smaller and is not desirable this way:

enter image description here

Here is my code for the frame:

Test.java

import javax.swing.BoxLayout;
import javax.swing.JFrame;

public class Test {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        //When you uncomment this, the button is sized really small
        //frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),BoxLayout.PAGE_AXIS));
        frame.add(new CButton("Hello"));
        frame.pack();
        frame.setVisible(true);
    }
}

And here is the code for the custom button, CButton:

CButton.java

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JToolTip;

public class CButton extends JButton implements ComponentListener {
    protected static final int BORDER_WIDTH = 5;
    private static final Insets INSETS_MARGIN = new Insets(2, 5, 2, 5);

    private static final long serialVersionUID = 1L;
    protected Area m_areaDraw = null;
    private Area m_areaFill = null;

    private double m_dHeightDraw = 0d;
    private double m_dHeightFill = 0d;
    private double m_dWidthDraw = 0d;

    private double m_dWidthFill = 0d;
    private int m_nMinHeight = 0;
    private int m_nMinWidth = 0;

    private int m_nStringHeightMax = 0;
    private int m_nStringWidthMax = 0;
    private RoundRectangle2D m_rrect2dDraw = null;
    private RoundRectangle2D m_rrect2dFill = null;
    private Shape m_shape = null;

    public CButton(String strLabel) {
        setContentAreaFilled(false);
        setMargin(INSETS_MARGIN);
        setFocusPainted(false);
        addComponentListener(this);
        setText(strLabel);
    }

    @Override
    public void componentHidden(ComponentEvent e) {
    }

    @Override
    public void componentMoved(ComponentEvent e) {
    }

    // Needed if we want this button to resize
    @Override
    public void componentResized(ComponentEvent e) {
        m_shape = new Rectangle2D.Float(0, 0, getBounds().width,
                getBounds().height);
        m_dWidthFill = (double) getBounds().width - 1;
        m_dHeightFill = (double) getBounds().height - 1;
        m_dWidthDraw = ((double) getBounds().width - 1)
                - (CButton.BORDER_WIDTH - 1);
        m_dHeightDraw = ((double) getBounds().height - 1)
                - (CButton.BORDER_WIDTH - 1);
        setShape();
        repaint();
    }

    @Override
    public void componentShown(ComponentEvent e) {
    }

    @Override
    public boolean contains(int nX, int nY) {
        if ((null == m_shape) || m_shape.getBounds().equals(getBounds())) {
            m_shape = new Rectangle2D.Float(0, 0, this.getBounds().width,
                    this.getBounds().height);
        }
        return m_shape.contains(nX, nY);
    }

    @Override
    public void paintBorder(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        RenderingHints hints = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHints(hints);
        g2.setColor(Color.black);
        Stroke strokeOld = g2.getStroke();
        g2.setStroke(new BasicStroke(CButton.BORDER_WIDTH,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        if (getModel().isRollover()) {
            g2.setColor(Color.ORANGE);
        }
        if (!getModel().isEnabled()) {
            g2.setColor(Color.GRAY);
        }
        g2.draw(m_areaDraw);
        g2.setStroke(strokeOld);
    };

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        RenderingHints hints = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHints(hints);
        if (getModel().isArmed()) {
            g2.setColor(Color.CYAN.darker());
        } else {
            g2.setColor(Color.CYAN);
        }
        g2.fill(m_areaFill);
        super.paintComponent(g2);
    }

    private void setShape() {
        // Area
        double dArcLengthFill = Math.min(m_dWidthFill, m_dHeightFill);
        m_rrect2dFill = new RoundRectangle2D.Double(0d, 0d, m_dWidthFill,
                m_dHeightFill, dArcLengthFill, dArcLengthFill);
        // WARNING: arclength and archeight are divided by 2
        // when they get into the roundedrectangle shape
        m_areaFill = new Area(m_rrect2dFill);
        // Border
        double dArcLengthDraw = Math.min(m_dWidthDraw, m_dHeightDraw);
        m_rrect2dDraw = new RoundRectangle2D.Double(
                (CButton.BORDER_WIDTH - 1) / 2, (CButton.BORDER_WIDTH - 1) / 2,
                m_dWidthDraw, m_dHeightDraw, dArcLengthDraw, dArcLengthDraw);
        m_areaDraw = new Area(m_rrect2dDraw);
    }

    @Override
    public void setText(final String strText) {
        super.setText(strText);
        Frame frame = JOptionPane.getRootFrame();
        FontMetrics fm = frame.getFontMetrics(getFont());
        m_nStringWidthMax = fm.stringWidth(getText());
        m_nStringWidthMax = Math.max(m_nStringWidthMax,
                fm.stringWidth(getText()));
        // WARNING: use getMargin. it refers to dist btwn text and border.
        // Also use getInsets. it refers to the width of the border
        int nWidth = Math.max(m_nMinWidth, m_nStringWidthMax + getMargin().left
                + getInsets().left + getMargin().right + getInsets().right);
        m_nStringHeightMax = fm.getHeight();
        // WARNING: use getMargin. it refers to dist btwn text and border.
        // Also use getInsets. it refers to the width of the border
        int nHeight = Math.max(m_nMinHeight, m_nStringHeightMax
                + getMargin().left + getInsets().left + getMargin().right
                + getInsets().right);
        setPreferredSize(new Dimension(
                nWidth + ((2 * getFont().getSize()) / 5), nHeight
                        + ((2 * getFont().getSize()) / 5)));
        // Set the initial draw and fill dimensions
        setShape();
    }
}

Is there a way I can fix this and make it the full size?

1 Answers1

1

Override the getPreferredSize(). BoxLayout respects preferred sizes. If you don't the preferred size will be determined by the text. It is bigger in the frame because the default BorderLayout of the frame doesn't respect preferred size, and will stretch the button. Another thing you can do instead is set bigger margins and/or bigger font, as that will also increase the preferred size. So you have a few options/things to consider

Have a look here as which layout respect preferred sizes and which ones don't. Another always good resources is Laying out Components Within a Container

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I set the preferred size int the `setText()` method. – Christopher Smith May 30 '14 at 17:08
  • @user3669858 [CustomButtunUI doesn't required most of part your methods](http://stackoverflow.com/a/5755124/714968), you mixing alpple with bananas, maybe better could be overide paintComponent for JButton just an only, nothing else – mKorbel May 30 '14 at 17:09
  • @mKorbel I am not using a CustomButtonUI, I am simply overriding the JButton class. – Christopher Smith May 30 '14 at 17:14
  • This might be better shown if you set the layout of the frame to a `FlowLayout`, this shows the button with a size much bigger than the `BoxLayout` button. – Christopher Smith May 30 '14 at 17:18