圆角LineBorder-并非所有角都是圆角的

时间:2018-10-11 11:42:03

标签: java swing tooltip jfreechart java-10

我正在使用JFreeChart,我想通过创建自己的ToolTip来自定义Class,该ChartPanel扩展了createToolTip()并覆盖了static private class PrivateChartPanel extends ChartPanel{ //constructors @Override public JToolTip createToolTip() { JToolTip jtt = super.createToolTip(); jtt.setBackground(Color.WHITE); jtt.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1, true)); return jtt; } }

Border

问题出在import java.awt.Color; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; public class HelloWorld { public static void main(String[] args) { JFrame a = new JFrame(); a.setBounds(100, 100, 100, 100); a.setLayout(null); JPanel b = new JPanel(); b.setBounds(5, 5, 50, 50); b.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1, true)); a.add(b); a.setVisible(true); } } 。并非在所有角落都是圆的。

tooltip-border-problem

为什么它没有四舍五入,我该怎么做?

P.S .:我创建了一个新的简单项目

Java 10

和JPanel的边框存在相同的问题。我正在使用factorial

1 个答案:

答案 0 :(得分:3)

圆角的效果取决于这些圆角的大小。对于LineBorder,它由thickness属性确定。相关的实现代码如下所示:

int offs = this.thickness;
int size = offs + offs;
if (this.roundedCorners) {
    float arc = .2f * offs;
    outer = new RoundRectangle2D.Float(x, y, width, height, offs, offs);
    inner = new RoundRectangle2D.Float(x + offs, y + offs, width - size, height - size, arc, arc);
}
else {
    outer = new Rectangle2D.Float(x, y, width, height);
    inner = new Rectangle2D.Float(x + offs, y + offs, width - size, height - size);
}
Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
path.append(outer, false);
path.append(inner, false);
g2d.fill(path);

因此,它区分内角和外角,这对于行大小为1的意义不大。但更糟糕的是,外角的大小仅为offs,与thickness(在您的情况下为一个)相同,而内圆角的大小由arc确定,即.2f * offs。对于您的thickness,结果的内角尺寸为0.2。因此,在左上角看到一个效果似乎是纯粹的巧合(这两个不同角的取整问题),因为即使更大的一个外部角尺寸也不足以创建可见的圆形效果。

这是thickness的{​​{1}}的样子,其外角尺寸为20,内角尺寸为20:< / p>

Screenshot with border thickness of 20

不知道Swing开发人员在此类中添加圆角支持时会想到哪个实际用例。我无法想象这种策略有用的任何情况。

实施有意义的4并不难。一种可能的实现方式如下:

Border

现在,当我换行时

public class RoundedLineBorder extends AbstractBorder {
    int lineSize, cornerSize;
    Paint fill;
    Stroke stroke;
    private Object aaHint;

    public RoundedLineBorder(Paint fill, int lineSize, int cornerSize) {
        this.fill = fill;
        this.lineSize = lineSize;
        this.cornerSize = cornerSize;
        stroke = new BasicStroke(lineSize);
    }
    public RoundedLineBorder(Paint fill, int lineSize, int cornerSize, boolean antiAlias) {
        this.fill = fill;
        this.lineSize = lineSize;
        this.cornerSize = cornerSize;
        stroke = new BasicStroke(lineSize);
        aaHint = antiAlias? RenderingHints.VALUE_ANTIALIAS_ON: RenderingHints.VALUE_ANTIALIAS_OFF;
    }

    @Override
    public Insets getBorderInsets(Component c, Insets insets) {
        int size = Math.max(lineSize, cornerSize);
        if(insets == null) insets = new Insets(size, size, size, size);
        else insets.left = insets.top = insets.right = insets.bottom = size;
        return insets;
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2d = (Graphics2D)g;
        Paint oldPaint = g2d.getPaint();
        Stroke oldStroke = g2d.getStroke();
        Object oldAA = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        try {
            g2d.setPaint(fill!=null? fill: c.getForeground());
            g2d.setStroke(stroke);
            if(aaHint != null) g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, aaHint);
            int off = lineSize >> 1;
            g2d.drawRoundRect(x+off, y+off, width-lineSize, height-lineSize, cornerSize, cornerSize);
        }
        finally {
            g2d.setPaint(oldPaint);
            g2d.setStroke(oldStroke);
            if(aaHint != null) g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAA);
        }
    }
}

在您的示例中

b.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1, true));

我明白了

Screenshot with custom border