JavaFX的。画一个球并从中心拖出一条线

时间:2017-10-31 09:26:55

标签: java javafx mouseevent

想法是在MOUSE_CLICKED上画一个球 并从其中心开始绘制一条直到它在MOUSE_DRAGGED处理程序中释放的行。 但它完全相反,我不是简单地得到它 - 它首先画一条线,然后我释放鼠标后出现球。 有谁看到问题出在哪里?

public class Step extends Application {

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

    @Override
    public void start(Stage stage) {
        Canvas layer1 = new Canvas(500, 500);
        Group root = new Group();
        root.getChildren().add(layer1);

        Ball c_ball = new Ball(0, 0, 50, 0, 0);
        Arrow arrow = new Arrow(0, 0, 0, 0);

        layer1.addEventHandler(MouseEvent.MOUSE_CLICKED,
                ev -> {
                    c_ball.x = ev.getX();
                    c_ball.y = ev.getY();
                    arrow.start_x = ev.getX();
                    arrow.start_y = ev.getY();
                    GraphicsContext gc = layer1.getGraphicsContext2D();
                    gc.setFill(Color.DARKCYAN);
                    gc.fillOval(c_ball.x - c_ball.size / 2, c_ball.y - c_ball.size / 2, c_ball.size, c_ball.size);
                });

        layer1.addEventHandler(MouseEvent.MOUSE_DRAGGED,
                ev -> {
                    GraphicsContext gc_arr = layer1.getGraphicsContext2D();
                    gc_arr.clearRect(0, 0, layer1.getWidth(), layer1.getHeight());
                    gc_arr.strokeLine(arrow.start_x, arrow.start_y, ev.getX(), ev.getY());
                });

        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.show();

    }
}

这是班级球:

public class Ball {
public double x, y;
public double dx, dy;
public double size;


public Ball(double x, double y, double size, double dx, double dy) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.dx = dx;
    this.dy = dy;

}}

箭头

public class Arrow  {
public double start_x, start_y;
public double end_x, end_y;

public Arrow(double x1, double y1, double x2, double y2) {
    this.start_x = x1;
    this.start_y = y1;
    this.end_x = x2;
    this.end_y = y2;
}}

1 个答案:

答案 0 :(得分:3)

查看MouseEvent.MOUSE_CLICKED文档,您将看到:

  

EventType javafx.scene.input.MouseEvent.MOUSE_CLICKED

     

单击鼠标按钮时会发生此事件(按下并按下)   在同一节点上发布)。此事件提供类似按钮   行为到任何节点。请注意,即使很长的拖动也会产生咔嗒声   event(它被传递到鼠标所在的最顶层节点   按下和释放)。

您正在寻找的鼠标事件是MouseEvent.MOUSE_PRESSED但是如果您的代码不能正常工作。原因是当你调用gc_arr.clearRect(0, 0, layer1.getWidth(), layer1.getHeight());时,你清除了MOUSE_DRAGGED事件中的所有内容。因此你将绘制圆圈,但是你将清除画布并仅绘制线条。如果删除该行,每次拖动鼠标时都会有多行,但这是一个不同的问题。

你需要退后一步思考,我真的需要用Canvas实现我的程序吗?

如果答案是,您将需要保留一个列表(或某些数据结构,如数组等)所有组件,当您想要更改某些内容时,需要更新对象并重新绘制一切

如果答案是,那么您正在采取正确的方法,您需要将画布更改为AnchorPane或Pane等,然后直接在节点上添加节点(圆形,线条等)窗格。

这是一个使用AnchorPane而不是Canvas的简单示例。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class ShapesTest extends Application {

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

    private double arrayStartX;
    private double arrayStartY;
    private AnchorPane root;
    private Line l;

    @Override
    public void start(Stage stage) {

        root = new AnchorPane();

        root.addEventHandler(MouseEvent.MOUSE_PRESSED, ev -> {
            addBall(ev.getX(), ev.getY());
            arrayStartX = ev.getX();
            arrayStartY = ev.getY();

        });

        root.addEventHandler(MouseEvent.MOUSE_DRAGGED, ev -> {
            if (l == null) {
                addLine(ev.getX(), ev.getY());
            } else {
                l.setEndX(ev.getX());
                l.setEndY(ev.getY());
            }

        });

        root.addEventHandler(MouseEvent.MOUSE_RELEASED, ev -> {
            l = null;
        });

        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.show();

    }

    private void addLine(double x, double y) {
        l = new Line(arrayStartX, arrayStartY, x, y);
        root.getChildren().add(l);

    }

    private void addBall(double x, double y) {
        Circle c = new Circle(x, y, 15);
        c.fillProperty().set(Color.DARKCYAN);
        root.getChildren().add(c);
    }
}

在上面的示例中,如果您愿意,可以将Circle和Lines信息保存在您自己的自定义对象上,然后在释放鼠标时对每个球应用物理。