Pregunta

Quiero crear un borde personalizado con esquinas redondeadas.

Código -

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;

class JRoundedCornerBorder extends AbstractBorder 
{   
    private static final long serialVersionUID = 7644739936531926341L;
    private static final int THICKNESS = 5;

    JRoundedCornerBorder()
    {
        super();
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) 
    {
        Graphics2D g2 = (Graphics2D)g.create();

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        if(c.hasFocus())
        {
            g2.setColor(Color.BLUE);
        }
        else
        {
            g2.setColor(Color.BLACK);
        }
        g2.setStroke(new BasicStroke(THICKNESS, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.drawRect(x, y, width - 1, height - 1);

        g2.dispose();
    }

    @Override
    public Insets getBorderInsets(Component c) 
    {
        return new Insets(THICKNESS, THICKNESS, THICKNESS, THICKNESS);
    }

    @Override
    public Insets getBorderInsets(Component c, Insets insets) 
    {
        insets.left = insets.top = insets.right = insets.bottom = THICKNESS;
        return insets;
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run() 
            {
                final JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new FlowLayout());

                // Add button with custom border
                final JButton button = new JButton("Hello");
                button.setBorder(new JRoundedCornerBorder());
                frame.add(button);

                // Add button without custom border
                frame.add(new JButton("Goodbye"));

                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

Resultado -

enter image description here

Como se puede ver, Graphics.drawRect ignora por completo el BasicStroke.CAP_ROUND y BasicStroke.JOIN_ROUND atributos.¿Por qué?

¿Fue útil?

Solución

Como se explica en Aprender Java 2D, Parte 1:

java.awt.BasicStroke.CAP_ROUND:Esto forma una tapa circular centrada en el extremo, con un diámetro del ancho de la pluma.

La palabra clave es "centrado".Creo que siempre se da el caso de que al dibujar con trazos gruesos, Java2D centrará el grosor de la línea a lo largo de la línea hipotética, infinitamente delgada, entre los centros de los píxeles en las coordenadas inicial y final.Por ejemplo, al dibujar una línea azul vertical de 7 píxeles de espesor, Java2D pinta 3 píxeles a cada lado del segmento de línea hipotético que se está dibujando.

En su ejemplo, el grosor es de 5 píxeles.Debes desplazar las coordenadas para dibujar el trazo completamente dentro del clip de gráficos.Moviéndose en 2 píxeles (o THICKNESS/2), se hacen visibles las esquinas redondeadas:

Screenshot of the GUI after moving in 2 pixels

//...
        g2.setStroke(new BasicStroke(THICKNESS, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.drawRect(x + THICKNESS/2, y + THICKNESS/2, width - 2*(THICKNESS/2) - 1, height - 2*(THICKNESS/2) - 1);

        g2.dispose();
    }

    @Override
    public Insets getBorderInsets(Component c) {
        return new Insets(THICKNESS + THICKNESS/2, THICKNESS + THICKNESS/2, THICKNESS + THICKNESS/2, THICKNESS + THICKNESS/2);
    }
//...

Otros consejos

el problema es el desplazamiento: efectivamente está cortando el borde en el medio para que las esquinas parezcan no estar redondeadas.Teniéndolo en cuenta (aquí solo para el desplazamiento, también es necesario ajustar el ancho)

   g2.drawRect(x + thickness/2, y + thickness/2, 
       width - 1 - thickness, height - 1 - thickness);

<×Editar

Recuento de píxeles descuidado fijo :-)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top