Search code examples
javaswingjpaneljtextfieldrounded-corners

How to make half rounded border?


I have a RoundPanel class that extends JPanel and provides a rounded appearance.

JPanel user_icon = new RoundPanel(8);
user_icon.setBackground(Color.decode("#363b41"));
user_icon.setBorder(null);
user_icon.setBounds(160, 135, 40, 46);
container.add(user_icon);
user_icon.setLayout(null);
public class RoundPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private Shape shape;
    
    public RoundPanel(int size) {
        setOpaque(false);
    }
    
    protected void paintComponent(Graphics g) {
         g.setColor(getBackground());
         g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 8, 8);
         super.paintComponent(g);
    }
    
    protected void paintBorder(Graphics g) {
         g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 8, 8);
    }
    
    public boolean contains(int x, int y) {
         if (shape == null || !shape.getBounds().equals(getBounds())) {
             shape = new RoundRectangle2D.Float(0, 0, getWidth()-1, getHeight()-1, 8, 8);
         }
         return shape.contains(x, y);
    }
}

want to modify it to have only the left corners rounded. (Half rounded, Half none)


Solution

  • I would, strongly, recommend taking the time to read through Working with Geometry, actually, I also recommend taking the time to read through the entire 2D Graphics trail while you're at it.

    No one example/solution will ever meet your requirements 100%, you need to be prepared to put in the time to try different solutions and adapt the ones you like to your needs, this is the mark of a good developer.

    So, with a little bit of experimentation (and a lot of reading through my previous answers) I was able to come up with...

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.geom.Path2D;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Set;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame("Test");
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        protected class TestPane extends JPanel {
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    
                g2d.setColor(Color.RED);
                RoundedShape shape = new RoundedShape(
                        20,
                        100, 200,
                        RoundedShape.Corner.TOP_LEFT,
                        RoundedShape.Corner.TOP_RIGHT,
                        RoundedShape.Corner.BOTTOM_RIGHT,
                        RoundedShape.Corner.BOTTOM_LEFT
                );
                g2d.translate(10, 10);
                g2d.draw(shape);
    
                g2d.dispose();
            }
        }
    
        public class RoundedShape extends Path2D.Double {
    
            enum Corner {
                TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT;
            }
    
            private double radius = 20;
            private Set<Corner> corners;
            private Dimension size;
    
            public RoundedShape(double radius, int width, int height, Corner... corners) {
                this.corners = new HashSet(Arrays.asList(corners));
                this.radius = radius;
                this.size = new Dimension(width, height);
    
                build();
            }
    
            protected void build() {
                moveTo(0, 0);
                if (corners.contains(Corner.TOP_LEFT)) {
                    moveTo(0, radius);
                    curveTo(0, radius, 0, 0, radius, 0);
                }
                if (corners.contains(Corner.TOP_RIGHT)) {
                    lineTo(size.width - radius, 0);
                    // Draw the curve here
                    curveTo(size.width - radius, 0,
                            size.width, 0,
                            size.width, radius);
                } else {
                    lineTo(size.width, 0);
                }
                if (corners.contains(Corner.BOTTOM_RIGHT)) {
                    lineTo(size.width, size.height - radius);
                    // Draw the curve here
                    curveTo(size.width, size.height - radius,
                            size.width, size.height,
                            size.width - radius, size.height);
                } else {
                    lineTo(size.width, size.height);
                }
                if (corners.contains(Corner.BOTTOM_LEFT)) {
                    lineTo(radius, size.height);
                    // Draw the curve here
                    curveTo(radius, size.height,
                            0, size.height,
                            0, size.height - radius);
                } else {
                    lineTo(0, size.height);
                }
                closePath();
            }
        }
    }
    

    I suggest having a look at Drawing a curve in Java using mouse drag, as working with Bézier curve always confuses me.

    You may also consider look at: