java - Path2D 绘制错误?

标签 java awt

我一直在与 Path2D.Double 合作现在大约一天左右,in this post 我请求有关设置控制点以允许路径通过指定点的帮助。我将一些代码混合在一起作为快速测试床,随机生成点,然后根据上面帖子中提到的信息将路径弯曲到这些点。

这是可运行的代码,抱歉它是整体的,我希望它是可发布的,以便您可以跟随:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;

public class Curver {
    public static ArrayList<Point2D> points = new ArrayList<Point2D>();
    /**
     * @param args
     */
    public static void main(String[] args) {

        final JFrame window = new JFrame();
        window.setPreferredSize(new Dimension(500,500));
        window.setLocationRelativeTo(null); 

        window.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseClicked(MouseEvent e) {
                new Thread(new Runnable(){
                    @Override
                    public void run() {

                        Random random = new Random();

                        while(true){

                            points.add(new Point2D.Double(random.nextInt(window.getWidth()-1)+1,random.nextInt(window.getHeight()-1)+1));
                            System.out.println(points.size());

                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                        }

                    }

                }).start();
            }
        });


        window.pack();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);

        int div = 7;
        int d = 4;

        Path2D.Double path = new Path2D.Double();
        Point2D currentPoint;
        double startX, startY;
        double interiorX_In, interiorY_In;
        double interiorX_Out, interiorY_Out;
        double endX, endY;

        Graphics2D g;


        while(true){

            g = (Graphics2D) window.getGraphics();
            g.setColor(Color.blue);

            for(int i = 0; i < points.size(); i++){

                currentPoint = points.get(i);
                g.fillRect((int)currentPoint.getX(), (int)currentPoint.getY(), d, d);

                if (i == 0){ 
                    // Don't attempt any line drawing as we don't have enough points.
                    path.moveTo(currentPoint.getX(), currentPoint.getY());
                } else if (i == 1 && points.size() > 2){ 
                    // draw first curve with knowledge of third point (third point is not end point)
                    startX = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-1).getX()) / div; // from start
                    startY = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-1).getY()) / div;

                    interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX()) / div; // to interior
                    interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY()) / div;

                    path.curveTo(startX, startY, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());

                } else if (i == 1){ // Only 2 points in list so use a straight line until more points are available.
                    g.drawLine((int) points.get(i-1).getX(), (int) points.get(i-1).getY(), (int)currentPoint.getX(), (int)currentPoint.getY());
                } else if (i >= 1 && i < points.size()-1){ // interior to interior edge.

                    interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX()) / div; // from interior
                    interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY()) / div;

                    interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX()) / div; // to interior
                    interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY()) / div;

                    path.curveTo(interiorX_Out, interiorY_Out, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());

                } else { // from interior point to end point.

                    interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX()) / div; // from interior
                    interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY()) / div;

                    endX = currentPoint.getX() - (currentPoint.getX() - points.get(i-1).getX()) / div; // to end
                    endY = currentPoint.getY() - (currentPoint.getY() - points.get(i-1).getY()) / div;

                    path.curveTo(interiorX_Out, interiorY_Out, endX, endY, currentPoint.getX(), currentPoint.getY());

                }

            } // end for 

            g.clearRect(0, 0, window.getWidth(), window.getHeight());
            g.draw(path);
            path.reset();


            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } 
    } 
}
  • 只需单击 JFrame 即可开始绘制随机点 - 控制台将报告正在绘制的点的数量。

我遇到的问题是,一旦我向上或 60-65 个随机点,路径就会闪烁,并且似乎在屏幕上缩小,并且通常表现出奇怪的行为? 正如我所说,代码可能并不完美,所以任何人都可以给我一些关于如何减少错误的指示。

我认为奇怪的行为来自于每次重新绘制 JFrame 时构造越来越长的路径?也许有一种方法可以将路径绘制为连续的线,因为我认为路径被解释为一系列线段?或者也许使路径累积而不是为运行循环的每次迭代重建整个路径?

期待提供任何建议 - 但请尝试解释一下,因为我对绘画和路径等相对较新。

提前致谢。


感谢@camickr 的帖子。 这是重新编写的代码,可以完美运行,有 3,500 多个随机点,没有一个小故障:

> import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Random;

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

public class Curver extends JFrame implements ActionListener, MouseListener{

    public Timer animationTicker = new Timer(50, this);
    public ArrayList<Point2D> points = new ArrayList<Point2D>();
    private Canvas canvas;

    public Curver(){
        this.setPreferredSize(new Dimension(500,500));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setLayout(new BorderLayout());
        canvas = new Canvas(points);
        this.add(canvas, BorderLayout.CENTER);
        this.addMouseListener(this);
        this.pack();
        this.setVisible(true);
    }

    class Canvas extends JPanel{

        int div = 7;
        int d = 4;

        Path2D.Double path = new Path2D.Double();
        Point2D currentPoint;
        double startX, startY;
        double interiorX_In, interiorY_In;
        double interiorX_Out, interiorY_Out;
        double endX, endY;
        Graphics2D g2;
        ArrayList<Point2D> points;

        public Canvas(ArrayList<Point2D> points){
            this.setMinimumSize(new Dimension(100,100));
            this.points = points;
        }

        @Override
        public void paintComponent(Graphics g) {

            g2 = (Graphics2D) g;
            g.setColor(Color.blue);

            synchronized(points){
            for(int i = 0; i < points.size(); i++){

                currentPoint = points.get(i);
                g2.fillRect((int)currentPoint.getX(), (int)currentPoint.getY(), d, d);

                if (i == 0){ 
                    // Don't attempt any line drawing as we don't have enough points.
                    path.moveTo(currentPoint.getX(), currentPoint.getY());
                } else if (i == 1 && points.size() > 2){ 
                    // draw first curve with knowledge of third point (third point is not end point)
                    startX = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-1).getX()) / div; // from start
                    startY = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-1).getY()) / div;

                    interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX()) / div; // to interior
                    interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY()) / div;

                    path.curveTo(startX, startY, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());

                } else if (i == 1){ // Only 2 points in list so use a straight line until more points are available.
                    g2.drawLine((int) points.get(i-1).getX(), (int) points.get(i-1).getY(), (int)currentPoint.getX(), (int)currentPoint.getY());
                } else if (i >= 1 && i < points.size()-1){ // interior to interior edge.

                    interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX()) / div; // from interior
                    interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY()) / div;

                    interiorX_In = currentPoint.getX() - (points.get(i+1).getX() - points.get(i-1).getX()) / div; // to interior
                    interiorY_In = currentPoint.getY() - (points.get(i+1).getY() - points.get(i-1).getY()) / div;

                    path.curveTo(interiorX_Out, interiorY_Out, interiorX_In, interiorY_In, currentPoint.getX(), currentPoint.getY());

                } else { // from interior point to end point.

                    interiorX_Out = points.get(i-1).getX() + (currentPoint.getX() - points.get(i-2).getX()) / div; // from interior
                    interiorY_Out = points.get(i-1).getY() + (currentPoint.getY() - points.get(i-2).getY()) / div;

                    endX = currentPoint.getX() - (currentPoint.getX() - points.get(i-1).getX()) / div; // to end
                    endY = currentPoint.getY() - (currentPoint.getY() - points.get(i-1).getY()) / div;

                    path.curveTo(interiorX_Out, interiorY_Out, endX, endY, currentPoint.getX(), currentPoint.getY());

                }

            } // end for 

            g.clearRect(0, 0, this.getWidth(), this.getHeight());
            g2.draw(path);
            path.reset();
            }
        }
    } // end of inner class

    @Override
    public void actionPerformed(ActionEvent e) {
        this.canvas.repaint();
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("Thread running");
                Random random = new Random();

                while(true){
                    synchronized(points){
                        points.add(new Point2D.Double(random.nextInt(getWidth()-1)+1,random.nextInt(getHeight()-1)+1));
                        System.out.println(points.size());
                    }
                    try {
                        Thread.sleep(60);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }

        }).start();
    }

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}


    public static void main(String[] args) {
        Curver curver = new Curver();
        curver.animationTicker.start();
    }
}

最佳答案

g = (Graphics2D) window.getGraphics();

我没有仔细查看您的代码,但论坛建议不要使用 getGraphics() 方法进行绘画。

自定义绘制是通过重写 JPanel(或 JComponent)的 PaintComponent() 方法来完成的。然后将面板添加到框架中。阅读 Swing 教程以获取有关自定义绘画的更多信息。

另外,不要使用“while (true)”逻辑。 Swing 将根据需要重新绘制。如果您想要某种动画,请使用 Swing Timer。

关于java - Path2D 绘制错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15884223/

相关文章:

java - 要删除的正则表达式

java - 在Android中获取 map 地址或位置地址

java - 使用反射加载 Java 对象会产生带有父类(super class)的 ClassNotFoundException

java - 如何在AndEngine中决定SVG Sprite 的宽度和高度

Java headless (headless)双三次图像调整大小

Java 窗口绘制问题

java - SWT列表拖放: Get element at drop location

java - 为什么我的Font是从文件创建的,为什么还要调用GraphicsEnvorinment.registerFont()?

Java AWT-EventQueue-0 错误

java - 使用 GridBagLayout 创建 JPanel,并在每列上创建 JPanel