Question

Je veux créer une bordure personnalisée avec des coins arrondis.

Code -

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

Résultat -

enter image description here

Comme tu peux le voir, Graphics.drawRect ignore complètement le BasicStroke.CAP_ROUND et BasicStroke.JOIN_ROUND les attributs. Pourquoi?

Était-ce utile?

La solution

Comme expliqué à Apprendre Java 2d, partie 1:

java.awt.BasicStroke.CAP_ROUND: Cela rend un capuchon circulaire centré sur le point d'extrémité, avec un diamètre de la largeur du stylo.

Le mot clé est "centré". Je crois que c'est toujours le cas que lors du dessin avec des traits épais, Java2d centrera l'épaisseur de la ligne le long de la ligne hypothétique et infiniment mince entre les centres des pixels aux coordonnées de départ et de fin. Par exemple, lors du dessin d'une ligne bleue verticale de 7 pixels d'épaisseur, Java2D peint 3 pixels de chaque côté du segment de ligne hypothétique qui est dessiné.

Dans votre exemple, l'épaisseur est de 5 pixels. Vous devez compenser les coordonnées pour dessiner complètement la course dans le clip graphique. En se déplaçant en 2 pixels (ou THICKNESS/2), les coins arrondis deviennent visibles:

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

Autres conseils

Le problème est le décalage: vous coupez efficacement la frontière au milieu afin que les coins ne semblent pas être arrondis. Le prendre en compte (ici uniquement pour le décalage, doit également régler la largeur)

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

Éditer

Compte de pixels bâclé fixes :-)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top