Frage

Ich möchte einen benutzerdefinierten Rahmen mit abgerundeten Ecken erstellen.

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

Ergebnis -

Bildbeschreibung hier eingeben

Wie Sie sehen können, ignoriert Graphics.drawRect die Attribute BasicStroke.CAP_ROUND und BasicStroke.JOIN_ROUND vollständig.Warum?

War es hilfreich?

Lösung

Wie unter Lernen von Java 2D, Teil 1 erläutert :

java.awt.BasicStroke.CAP_ROUND: Hiermit wird eine kreisförmige Kappe auf dem Endpunkt mit einem Durchmesser der Stiftbreite zentriert.

Das Schlüsselwort ist "zentriert". Ich glaube, dass Java2D beim Zeichnen mit dicken Strichen immer die Dicke der Linie entlang der hypothetischen, unendlich dünnen Linie zwischen den Mittelpunkten der Pixel an den Start- und Endkoordinaten zentriert. Wenn Sie beispielsweise eine vertikale blaue Linie mit einer Dicke von 7 Pixel zeichnen, malt Java2D 3 Pixel auf jeder Seite des hypothetischen Liniensegments, das gezeichnet wird.

In Ihrem Beispiel beträgt die Dicke 5 Pixel. Sie müssen die Koordinaten versetzen, um den Strich vollständig innerhalb des Grafikclips zu zeichnen. Durch Verschieben in 2 Pixel (oder THICKNESS/2) werden die abgerundeten Ecken sichtbar:

Screenshot der GUI nach dem Verschieben in 2 Pixel

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

Andere Tipps

Das Problem ist der Versatz: Sie schneiden den Rand in der Mitte effektiv ab, sodass die Ecken nicht abgerundet erscheinen.Berücksichtigen Sie dies (hier nur für den Versatz, müssen Sie auch die Breite anpassen)

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

Bearbeiten

Feste schlampige Pixelzählung :-)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top