3

这个问题是我前段时间问的一个问题的后续问题: 在 Java 中绘制带有尖角的边界路径

经过实验,我发现了一些可能是有意或可能是错误的行为,但我不希望任何一种方式。SSCCE:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class CornerTest {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CornerTest window = new CornerTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public CornerTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel() {
            protected void paintComponent(Graphics g) {
                GeneralPath path;
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setStroke(new BasicStroke(15.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.setColor(Color.BLACK);
                path = new GeneralPath();
                path.moveTo(100, 100);
                path.lineTo(200, 100);
                path.lineTo(100, 50);
                g2d.draw(path);
            }
        };
        frame.setBackground(Color.CYAN);
        frame.add(panel);
    }
}

通过取线path.lineTo(100, 50);并使用第二个参数,我们可以改变绘制路径的角度。有关各种示例,请参见下图。

在此处输入图像描述

基本上,我GeneralPath在每个图像中绘制角度略微减小的 a。最终(在底部图像中)角度达到零。在这种情况下,圆形的“连接”不再被绘制。这种说法是有道理的,但又不是。我不确定这是否是有意的。有趣的是,如果将角度更改为略大于0(即通过将上面引用的线更改为path.lineTo(100, 99.999);圆角,则会再次绘制。

在我的应用程序中,路径可能会在自身上加倍(即创建零度角),在这种情况下,在这种情况下绘制连接圆在美学上更具吸引力。有什么办法可以破解 Java 源代码来完成这项工作吗?

4

2 回答 2

3

我正在绘制带有 500 多个点的非常长的路径,它会为我的绘制方法增加很多开销来检查每个“子路径”

不要在 paint 方法中构建 GeneralPath。您可以使用一个包装器类,它会在添加每个点时对其进行过滤。此处的代码将在每次要添加一个点时比较直线的斜率。当斜率相同时,为添加moveTo之前的最后一个点生成a lineTo。这将导致生成圆形笔划:

import java.awt.*;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.*;
import java.util.List;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class CornerTest {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CornerTest window = new CornerTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public CornerTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 450);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final GeneralPath gp = new GeneralPath();
        MyGeneralPath path = new MyGeneralPath(gp);
        path.moveTo(100, 100);
        path.lineTo(200, 100);
        path.lineTo(100, 50);
//        path.lineTo(50, 100);
        path.flush();


        JPanel panel = new JPanel() {
            protected void paintComponent(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setStroke(new BasicStroke(15.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.setColor(Color.BLACK);
                g2d.draw(gp);
            }
        };
        frame.setBackground(Color.CYAN);
        frame.add(panel);
    }

    static class MyGeneralPath
    {
        private GeneralPath path;
        private List<Point2D.Double> points = new ArrayList<Point2D.Double>();

        public MyGeneralPath(GeneralPath path)
        {
            this.path = path;
        }

        public void moveTo(double x, double y)
        {
            flush();
            points.add( new Point2D.Double(x, y) );
        }

        public void lineTo(double x, double y)
        {
            Point2D.Double point = new Point2D.Double(x, y);

            checkSlope(point);

            points.add( point );
        }

        private void checkSlope(Point2D.Double p3)
        {
            int size = points.size();

            if (size < 2 )
                return;

            Point2D.Double p2 = points.get(size - 1);
            Point2D.Double p1 = points.get(size - 2);

            double slope1 = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
            double slope2 = (p3.getY() - p2.getY()) / (p3.getX() - p2.getX());

            if (slope1 == slope2)
                moveTo(p2.getX(), p2.getY());
        }

        public void flush()
        {
            int size = points.size();

            if (size == 0)
                return;

            Point2D.Double point = points.get(0);
            path.moveTo(point.getX(), point.getY());

            for (int i = 1; i < size; i++)
            {
                point = points.get(i);
                path.lineTo(point.getX(), point.getY());
            }

            points.clear();
        }
    }
}
于 2013-03-23T04:47:17.750 回答
2

不知道如何破解源代码,但您可以通过仅绘制一条线来自定义代码以解决此行为:

path = new GeneralPath();
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(50, 100);

Rectangle bounds = path.getBounds();

if (bounds.height == 0)
{
    path = new GeneralPath();
    path.moveTo(bounds.x, bounds.y);
    path.lineTo(bounds.x + bounds.width, bounds.y);
}

if (bounds.width == 0)
{
    path = new GeneralPath();
    path.moveTo(bounds.x, bounds.y);
    path.lineTo(bounds.x, bounds.y + bounds.height);
}

g2d.draw(path);
于 2013-03-23T01:29:44.250 回答