简体   繁体   English

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

[英]Rounded LineBorder - not all corners are rounded

I'm using JFreeChart and I want to customise the ToolTip by creating my own Class which extends ChartPanel and override createToolTip() . 我正在使用JFreeChart ,我想通过创建自己的扩展ChartPanel并覆盖createToolTip()Class来自定义ToolTip

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;

    }

}

The problem is at Border . 问题出在Border It is not rounded on all corners. 并非在所有角落都是圆的。

提示-边界问题

Why it is not rounded on all corners and how I could done it? 为什么它不能在所有角落都圆满,我该怎么做?

PS: I created a new simple project PS:我创建了一个新的简单项目

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

  }

}

and Border of JPanel is with same problem. 和JPanel的边框有同样的问题。 I'm using Java 10 我正在使用Java 10

The effect of rounded corners depends on the size of these rounded corners. 圆角的效果取决于这些圆角的大小。 In case of LineBorder , it is determined by the thickness property. LineBorder情况下,由thickness属性确定。 This is how the relevant implementation code looks like: 相关的实现代码如下所示:

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

So it differentiates between inner and outer corner, which is not much meaningful for a line size of one. 因此,它可以区分内角和外角,这对于线大小为1的线没有太大意义。 But even worse, the outer corner size is just offs , which is identical to thickness (one in your case) and the size of the inner rounded corner is determined by arc , which is .2f * offs . 但更糟糕的是,外角的大小刚好offs ,它等于thickness (在您的情况下为一个),而内圆角的大小由arc确定,即.2f * offs For your thickness of one, the resulting inner corner size is 0.2 . 对于您的thickness 1,所得的内角尺寸为0.2 So it seems to be a pure coincidence (rounding issue of these two different corners) that we see an effect in the upper left corner, as even the bigger outer corner size of one is not enough to create a visible rounded effect. 因此,在左上角看到一个效果似乎是纯粹的巧合(这两个不同角的取整问题),因为即使更大的一个外部角尺寸也不足以创建可见的圆形效果。

Here is how it looks like with a thickness of 20 , which results in an outer corner size of 20 and a whopping inner corner size of 4 : thickness20时的外观如下所示,其外角尺寸为20而内角尺寸高达4

屏幕截图,边框厚度为20

It don't know which actual use case the Swing developers had in mind when they added the rounded corner support in this class. 它不知道Swing开发人员在此类中添加圆角支持时会想到哪个实际用例。 I can't imagine any scenario where this strategy is useful. 我无法想象这种策略有用的任何情况。

Implementing a meaningful Border is not that hard. 实施有意义的Border并不难。 One possible implementation looks like: 一种可能的实现如下所示:

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

Now, when I change the line 现在,当我换线时

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

in your example to 在你的例子中

b.setBorder(new RoundedLineBorder(Color.BLACK, 1, 10, true));

I get 我懂了

带有自定义边框的屏幕截图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM