drawArc() 弧长变化时渲染不一致

时间:2021-05-01 18:55:10

标签: java swing

我需要在音量旋钮周围画一条弧线,弧长代表音量。

我尝试了 Graphics.drawArc() 和 Arc2D.Double,但结果并不好:对于不同的范围值,弧的路径并不完全相同。

enter image description here

public class ArcComponent extends JComponent
{

    private ImageIcon knobImage = new ImageIcon(ArcComponent.class.getResource("Knob-w37.png"));

    int arcLength = 220;        // Degrees

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // Paint knob image
        knobImage.paintIcon(this, g2, 20, 20);

        // Add arc
        var arc = new Arc2D.Double(22, 22, 32, 32, 220 - arcLength, arcLength, Arc2D.OPEN);
        g2.setColor(Color.CYAN);
        g2.setStroke(new BasicStroke(2));
        g2.draw(arc);

        g2.dispose();
    }

    void shorter()
    {
        arcLength -= 5;
        if (arcLength < 0)
        {
            arcLength = 260;
        }
        repaint();
    }

    void longer()
    {
        arcLength += 5;
        if (arcLength > 260)
        {
            arcLength = 0;
        }
        repaint();
    }
}

如何确保圆弧的路径始终相同?

编辑:添加旋钮图像绘制

enter image description here

2 个答案:

答案 0 :(得分:2)

一个肮脏的把戏:画一个完整的圆圈,然后用一个形状,背景颜色相同的颜色覆盖你不需要的部分。

像这样:

@Override
public void paintComponent(Graphics g)
{
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Shape circle=new Ellipse2D.Double(20, 20, 30, 30);
    g2.setColor(Color.CYAN);
    g2.setStroke(new BasicStroke(2f));
    g2.draw(circle);
    Shape arc=new Arc2D.Double(10,10,50,50,230,360-arcLength,Arc2D.PIE);
    g2.setColor(getBackground());
    g2.fill(arc);
    g2.dispose();
}

不幸的是,这需要在同一区域中的任何其他事物之前绘制弧线,但您可能可以解决这个问题。

EDIT:对于额外的约束,不一致的渲染实际上是由于笔划,所以尝试创建一个粗的形状并填充它,例如:

@Override
public void paintComponent(Graphics g)
{
    super.paintComponent(g);

    double thickness=8.0; //This replaces your stroke width
    
    GeneralPath shape=new GeneralPath();
    
    shape.append(new Arc2D.Double(20-thickness/2,20-thickness/2, 30+thickness, 30+thickness, 230, -arcLength, Arc2D.OPEN),false);
    shape.append(new Arc2D.Double(20+thickness/2,20+thickness/2, 30-thickness, 30-thickness, 230-arcLength, arcLength, Arc2D.OPEN),true);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.setColor(Color.CYAN);
    g2.fill(shape);
    g2.dispose();
}

答案 1 :(得分:0)

只需绘制一个完整的圆并夹在弧形上(使用一些填充以确保绘制所有内容)。

Graphics2D g2 = (Graphics2D) g.create();
Ellipse2D circle = new Ellipse2D.Double(20, 20, 30, 30);
int d = 2;
Arc2D arc = new Arc2D.Double(20 - d, 20 - d, 30 + 2 * d, 30 + 2 * d, 230, -arcLength, Arc2D.PIE);

g2.setColor(Color.CYAN);
g2.setClip(arc);
g2.setStroke(new BasicStroke(2f));
g2.draw(circle);

knobImage.paintIcon(this, g, 20, 20);