在BoxLayout中缩小自定义按钮

时间:2014-05-30 15:51:21

标签: java swing jbutton boxlayout

我创建了一个扩展JButton的自定义按钮类。当我将其添加到JFrame时,我得到了这个:

enter image description here

但是当我使用BoxLayout将此自定义按钮放入框架时,按钮会变小并且不希望这样:

enter image description here

这是我的框架代码:

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);
    }
}

这是自定义按钮的代码,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();
    }
}

有没有办法可以解决这个问题并使其达到最大尺寸?

1 个答案:

答案 0 :(得分:1)

覆盖getPreferredSize()。 BoxLayout尊重首选尺寸。如果您没有,首选大小将由文本决定。它在框架中更大,因为框架的默认BorderLayout不会考虑首选大小,并会拉伸按钮。你可以做的另一件事是设置更大的边距和/或更大的字体,因为这也会增加首选尺寸。所以你有几个选择/事情需要考虑

看看here哪个布局符合首选尺寸,哪些不适合。另一个总是很好的资源是Laying out Components Within a Container