有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JTEXTEXTAREA圆角

我想让JTextArea有一个圆角,我做了以下代码:

public BPosTxtArea() {
    super();
    setOpaque(false);
}

@Override
protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getBackground());
    g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
    super.paintComponent(g);
}

@Override
protected void paintBorder(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(new Color(102, 102, 102));
    g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}

但它的外部仍然有一个方形边框,如下图所示:

enter image description here

有人能帮我吗


共 (1) 个答案

  1. # 1 楼答案

    首先看一下How to Use Borders

    这是一个非常简单的例子:

    public class RoundBorder implements Border {
    
        private int radius;
    
        public RoundBorder(int radius) {
            this.radius = radius;
        }
    
        public int getRadius() {
            return radius;
        }
    
        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
            g2d.dispose();
        }
    
        @Override
        public Insets getBorderInsets(Component c) {
            int value = getRadius() / 2;
            return new Insets(value, value, value, value);
        }
    
        @Override
        public boolean isBorderOpaque() {
            return false;
        }
    
    }
    

    Rounded Border

    import java.awt.Component;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.geom.RoundRectangle2D;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.border.Border;
    
    public class Example {
    
        public static void main(String[] args) {
            new Example();
        }
    
        public Example() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
    
                JTextArea ta = new JTextArea(10, 20);
                ta.setBorder(new RoundBorder(20));
    
                JScrollPane sp = new JScrollPane(new JTextArea(10, 20));
                sp.setBorder(new RoundBorder(20));
    
                add(ta, gbc);
                add(sp, gbc);
            }
    
        }
    
        public class RoundBorder implements Border {
    
            private int radius;
    
            public RoundBorder(int radius) {
                this.radius = radius;
            }
    
            public int getRadius() {
                return radius;
            }
    
            @Override
            public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
                g2d.dispose();
            }
    
            @Override
            public Insets getBorderInsets(Component c) {
                int value = getRadius() / 2;
                return new Insets(value, value, value, value);
            }
    
            @Override
            public boolean isBorderOpaque() {
                return false;
            }
    
        }
    
    }
    

    问题是,边框被绘制在组件填充区域的“内部”,这意味着角落将与填充区域的颜色相同。使用Border无法解决这个问题

    诀窍是创建第二个组件,可以在其上绘制边框(通过paintComponent,将边框内的区域填充为与文本区域相同的颜色),然后将该组件添加到其中

    更新

    根据您的代码示例,您没有覆盖getInsets,这将是非常重要的,另一件事是,您的JTextArea似乎在JScrollPane之内

    Comparison

    public class BPosTextArea extends JTextArea {
    
        private int radius;
    
        public BPosTextArea() {
            super(10, 20);
            setOpaque(false);
            setBorder(null);
            setRadius(20);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(getBackground());
            g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
            super.paintComponent(g);
        }
    
        @Override
        protected void paintBorder(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(new Color(102, 102, 102));
            g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
        }
    
        public void setRadius(int radius) {
            this.radius = radius;
            repaint();
        }
    
        public int getRadius() {
            return radius;
        }
    
        @Override
        public Insets getInsets() {
            int value = getRadius() / 2;
            return new Insets(value, value, value, value);
        }
    
    }
    

    一种解决方案是将border设置为null以用于JScrollPane