使用鼠标拖动在Java中绘制曲线 [英] Drawing a curve in Java using mouse drag

查看:304
本文介绍了使用鼠标拖动在Java中绘制曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java的新手,正在尝试画一条曲线.我试图实现的功能是,曲线应通过鼠标拖动然后单击鼠标来定义. 拖动动作完成后,我希望从拖动开始到结束绘制一条线.在那之后单击画布应被视为定义曲线所必需的第三点,并且绘制的线应更改为曲线.
我怎么做? 我在这里浏览过有关如何绘制Bezier曲线的不同文章,但我非常困惑.这是我的大部分代码,它们使用鼠标事件绘制矩形,椭圆形和直线:

I am new to java and I am trying to draw a curve. The functionality I am trying to implement is that the curves should be defined by a mouse drag followed by a mouse click. Once the drag action is done, I want a line to be drawn from the start of the drag to the end. Clicking on the canvas after that should be considered the third point necessary to define the curve and the line drawn should be changed into a curve.
How do I do that? I've gone through different posts here about how to draw Bezier curves but I am super confused. Here's a chunk of my code to draw rectangles, ovals and lines using mouse events:

   public void mousePressed(MouseEvent e) {

        xCoordinateInitial = e.getX(); //Initialize x-coordinate to the mouse x-coordinate
        yCoordinateInitial = e.getY() + shiftInY; //Initialize y-coordinate to the mouse y-coordinate
        System.out.println("X-coordinate: " + xCoordinateInitial);
        System.out.println("Y-coordinate: " + yCoordinateInitial);
    }

    public void mouseReleased(MouseEvent e) {

        Graphics2D G = (Graphics2D) getGraphics();
        G.setStroke(new BasicStroke(lineThickness));
        G.setColor(colorSelected);
        G.setPaint(colorSelected);
        xCoordinateFinal = e.getX(); //Set final x-coordinate to the mouse x-coordinate after drag
        yCoordinateFinal = e.getY() + shiftInY; //Set final y-coordinate to the mouse y-coordinate after drag
        int x = xCoordinateInitial;
        int y = yCoordinateInitial;
        int width = xCoordinateFinal - xCoordinateInitial; //Setting width
        int height = yCoordinateFinal - yCoordinateInitial; //Setting height



        if (yCoordinateFinal < yCoordinateInitial) {
            y = yCoordinateFinal;
            height = yCoordinateInitial - yCoordinateFinal;
        }

        if (xCoordinateFinal < xCoordinateInitial) {
            x = xCoordinateFinal;
            width = xCoordinateInitial - xCoordinateFinal;
        }


        // Shape Selection
        switch (shapeSelected) {
            case Line:

                G.drawLine(xCoordinateInitial, yCoordinateInitial, xCoordinateFinal, yCoordinateFinal);
                break;

            case Rectangle:
                G.fillRect(x, y, width, height);
                break;

            case Oval:
                G.fillOval(x, y, width, height);
                break;

            case Curve :

                // To implement

        }

    }
});

我试图理解以下内容,但无法使其起作用:

I tried to understand the following but I couldn't make it work:

                        Path2D p = new GeneralPath();
                        p.moveTo(x1, y1);
                        p.curveTo(bx1, by1, bx2, by2, x2, y2);
                        G.draw(p);

推荐答案

首先阅读一下

Let's start by having a read through the JavaDocs for Path2D#curveTo

公共最终空隙curveTo(double x1,
y1的两倍,
双倍x2,
y2的两倍,
双倍x3,
double y3)

通过绘制一条Bézier曲线,将由三个新点定义的弯曲线段添加到路径中 与当前坐标和指定坐标相交 (x3,y3),使用指定点(x1,y1)和(x2,y2)作为Bézier 控制点.所有坐标均以双精度指定.

public final void curveTo(double x1,
double y1,
double x2,
double y2,
double x3,
double y3)

Adds a curved segment, defined by three new points, to the path by drawing a Bézier curve that intersects both the current coordinates and the specified coordinates (x3,y3), using the specified points (x1,y1) and (x2,y2) as Bézier control points. All coordinates are specified in double precision.

好吧,公平地说,这需要一点阅读才能理解,这也许可以通过一些图形更好地解决.

Okay, let's be fair, that takes a little bit of reading to understand, which is probably better addressed with some graphics.

基本概念是,您具有三个控制点,其中一个控制点充当观察"约束.

The basic concept is, you have three control points, one of which is acting as a "look at" constraint.

让我们假设您有三个点,anchortargetclick. anchor是第一个点,target是拖动到的点,click是拖动操作完成后单击的点.

Let's assume you have three points, anchor, target and click. anchor is the first point, target is the point dragged to and click is the point which was clicked AFTER the drag operation completed.

如果使用顺序anchor, target, click,则最终得到一条类似

If we use the order anchor, target, click, we end up with a curve looking something like

其中P1 == anchorP2 == targetP3 == click.如您所见,P2充当查看约束",并试图将结果曲线拉向该约束.

where P1 == anchor, P2 == target and P3 == click. As you can see, the P2 is acting as the "look at constraint" and is trying to pull the resulting curve towards it.

但是,如果相反,我们使用anchor, click, target,我们最终会遇到类似...

However, if, instead, we use anchor, click, target, we end up within something more like...

其中P1 == anchorP2 == clickP3 == target.如您所见,P2充当查看约束",并试图将生成的曲线向其拉.

where P1 == anchor, P2 == click and P3 == target. As you can see, the P2 is acting as the "look at constraint" and is trying to pull the resulting curve towards it.

这本质上就是贝塞尔曲线的工作原理

This is essentially how a Bézier curve works

好的,总的来说,我写了一些测试代码,您可以使用它们来更改参数并测试想法

Okay, so to put it all together, I wrote some test code, which you can use to change the parameter and test the idea

此示例所做的一件事是,在建立前两个点之后,随着鼠标的移动,绘制了预期曲线的伪"示例,从而使您对曲线的外观有了视觉反馈,直到用户单击鼠标并设置了路径

One thing this example does is it paints a "fake" example of the intended curve as the mouse is moved, after the first two points are established, giving you some visual feed back of what the curve will look like, until the user clicks the mouse and the path is set

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private boolean dragging = false;

        private Point anchor;
        private Point target;

        private Shape fakePath;

        private List<Shape> shapes = new ArrayList<>(25);

        public TestPane() {
            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    dragging = true;
                    target = new Point(e.getPoint());
                    repaint();
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    if (target != null && anchor != null) {
                        fakePath = makePath(anchor, e.getPoint(), target);
                        repaint();
                    }
                }

            });

            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    if (anchor == null) {
                        target = null;
                        anchor = new Point(e.getPoint());
                    }
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    dragging = false;
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    if (anchor != null && target != null) {
                        fakePath = null;

                        shapes.add(makePath(anchor, e.getPoint(), target));

                        anchor = null;
                        target = null;

                        repaint();
                    }
                }
            });
        }

        protected Path2D makePath(Point p1, Point p2, Point p3) {
            Path2D p = new GeneralPath();
            p.moveTo(p1.getX(), p1.getY());
            p.curveTo(p1.getX(), p1.getY(),
                            p2.getX(), p2.getY(),
                            p3.getX(), p3.getY());

            return p;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setColor(Color.BLACK);
            for (Shape shape : shapes) {
                g2d.draw(shape);
            }
            if (anchor != null && target != null) {
                g2d.setColor(Color.GREEN);
                g2d.draw(new Line2D.Double(anchor, target));
            }
            if (fakePath != null) {
                g2d.setColor(Color.BLUE);
                g2d.draw(fakePath);
            }
            g2d.dispose();
        }

    }

}

这篇关于使用鼠标拖动在Java中绘制曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆