【问题标题】:Rounded LineBorder - not all corners are roundedRounded LineBorder - 不是所有的角都是圆形的
【发布时间】:2018-10-11 11:42:02
【问题描述】:

我正在使用JFreeChart,我想通过创建自己的Class 来自定义ToolTip,它扩展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。它不是所有角都圆润的。

为什么它不是所有角都圆润的,我是怎么做到的?

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

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

  }

}

和 JPanel 的边框也有同样的问题。我正在使用Java 10

【问题讨论】:

  • ChartPanel 是否会覆盖边框?您是否尝试过在其他组件上使用边框?
  • @camickr 我不知道该说什么@Override Border。我使用来自javax.swingBorderFactory。但是我用this codeBorder 创建了一个新的简单项目JPanel 也有同样的问题。 P.S.:我使用Java10
  • 发布在您的问题中演示问题的代码。然后我们可以复制/粘贴,看看我们是否有同样的问题,或者这可能是版本/平台问题。
  • @camickr here 是一个有同样问题的样本,对我来说。
  • 代码应该与您的问题一起发布,而不是在其他网站上。

标签: java swing tooltip jfreechart java-10


【解决方案1】:

圆角的效果取决于这些圆角的大小。对于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);

所以它区分了内角和外角,这对于一号线的大小没有多大意义。但更糟糕的是,外角大小只是offs,与thickness(在您的情况下为一个)相同,而内圆角的大小由arc 确定,即.2f * offs。对于您的thickness 之一,生成的内角大小为0.2。因此,我们在左上角看到效果似乎纯属巧合(这两个不同角的圆角问题),因为即使一个较大的外角尺寸也不足以产生可见的圆角效果。

下面是thickness20 的样子,这导致外角大小为20,内角大小为4

它不知道 Swing 开发人员在这个类中添加圆角支持时想到的是哪个实际用例。我无法想象这种策略有什么用处。

实现一个有意义的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));

在你的例子中

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

我明白了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多