[英]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
: thickness
为20
时的外观如下所示,其外角尺寸为20
而内角尺寸高达4
:
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.