JavaFX Circle对象未正确注册鼠标事件 [英] JavaFX Circle object not registering mouse events properly

查看:148
本文介绍了JavaFX Circle对象未正确注册鼠标事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望用户能够拖动窗格周围的圆圈。圈子似乎没有注册(几乎)没有鼠标事件(最终定义)。我有一个空窗格的相同的确切代码,它工作得很好。此外,如果我改变

I want the user to be able to drag-move the circles around the pane. The circles dont seem to register (almost) no mouse events (as defined in the end). I have the same exact code for an empty pane it works just fine. Also if I change

circle1.setOnMouseDragged

paneForCircles.setOnMouseDragged

它运作得很好,但它不是我想要的,因为我需要操纵两个圆圈。有任何想法吗 ?如果您还可以告诉我如何隐藏与相邻元素重叠的圆圈部分,如果它的中心太靠近窗格边框,我将不胜感激。

it works just fine but its not what I want because I need to manipulate both circles. Any ideas ? I would appreciate it if you could also tell me how to hide the part of the circle that overlaps with the adjacent elements if its center is too close to the pane border.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle; 
import javafx.stage.Stage;


public class Ex168 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
    Circle circle1 = new Circle(30);
    Circle circle2 = new Circle(35);
    circle1.setCenterX(100);
    circle1.setCenterY(100);
    circle2.setCenterX(150);
    circle2.setCenterY(120);
    circle1.setStroke(Color.BLACK);
    circle1.setFill(null);
    circle2.setStroke(Color.BLACK);
    circle2.setFill(null);

    VBox vBoxForScene = new VBox(5);
    vBoxForScene.setPadding(new Insets(5));
    vBoxForScene.setAlignment(Pos.TOP_CENTER);

    Pane paneForCircles = new Pane();
    paneForCircles.setStyle("-fx-border-color: black");
    vBoxForScene.heightProperty().addListener(ov -> paneForCircles.setPrefHeight(vBoxForScene.heightProperty().divide(1.2).doubleValue()));
    paneForCircles.setPrefHeight(300);
    HBox hBoxForFields = new HBox(5);
    hBoxForFields.setAlignment(Pos.CENTER);
    hBoxForFields.setSpacing(5);

    // VBofForLeftFields
    VBox vBoxForLeftFields = new VBox(5);
    vBoxForLeftFields.setAlignment(Pos.CENTER_LEFT);
    Label lblCircle1 = new Label("Enter Circle 1 info");
    lblCircle1.setAlignment(Pos.TOP_LEFT);
    TextField tfCircle1CenterX = new TextField();
    tfCircle1CenterX.textProperty().bind(circle1.centerXProperty().asString());
    TextField tfCircle1CenterY = new TextField();
    tfCircle1CenterY.textProperty().bind(circle1.centerYProperty().asString());
    TextField tfCircle1Radius = new TextField();
    tfCircle1Radius.textProperty().bind(circle1.radiusProperty().asString());
    tfCircle1CenterX.setPrefColumnCount(5);
    tfCircle1Radius.setPrefColumnCount(5);
    tfCircle1CenterY.setPrefColumnCount(5);
    Label lblCenterX = new Label("Center x:", tfCircle1CenterX);
    Label lblCenterY = new Label("Center x:", tfCircle1CenterY);
    Label lblCircle1Radius= new Label("Radius:   ", tfCircle1Radius);
    lblCenterX.setContentDisplay(ContentDisplay.RIGHT);
    lblCenterY.setContentDisplay(ContentDisplay.RIGHT);
    lblCircle1Radius.setContentDisplay(ContentDisplay.RIGHT);

    //VBoxForRightFields
    VBox vBoxForRightFields = new VBox(5);
    Label lblCircle2 = new Label("Enter Circle 2 info");
    TextField tfCircle2CenterX = new TextField();

    TextField tfCircle2CenterY = new TextField();
    TextField tfCircle2Radius = new TextField();
    tfCircle2CenterX.setPrefColumnCount(5);
    tfCircle2CenterX.textProperty().bind(circle2.centerXProperty().asString());
    tfCircle2Radius.setPrefColumnCount(5);
    tfCircle2Radius.textProperty().bind(circle2.radiusProperty().asString());
    tfCircle2CenterY.setPrefColumnCount(5);
    tfCircle2CenterY.textProperty().bind(circle2.centerYProperty().asString());
    Label lblCenter2X = new Label("Center x:", tfCircle2CenterX);
    Label lblCenter2Y = new Label("Center x:", tfCircle2CenterY);
    Label lblCircle2Radius= new Label("Radius:   ", tfCircle2Radius);
    lblCenter2X.setContentDisplay(ContentDisplay.RIGHT);
    lblCenter2Y.setContentDisplay(ContentDisplay.RIGHT);
    lblCircle2Radius.setContentDisplay(ContentDisplay.RIGHT);
    vBoxForRightFields.getChildren().addAll(lblCircle2, lblCenter2X, lblCenter2Y, lblCircle2Radius);

    vBoxForLeftFields.getChildren().addAll(lblCircle1, lblCenterX, lblCenterY, lblCircle1Radius);
    hBoxForFields.getChildren().addAll(vBoxForLeftFields, vBoxForRightFields);
    Label lblResult = new Label("Do the two circles intersect?");
    Button btReDrawCircles = new Button("Redraw Circles");
    vBoxForScene.getChildren().addAll(lblResult, paneForCircles, hBoxForFields, btReDrawCircles);

    circle1.setOnMouseDragged(e -> {
        System.out.println(e.getX());
        circle1.setCenterX(e.getX());
        circle1.setCenterY(e.getY());
    });

    circle2.setOnMouseDragged(e -> {

        circle2.setCenterX(e.getX());
        circle2.setCenterY(e.getY());
    });

    paneForCircles.getChildren().addAll(circle1, circle2);
    Scene scene = new Scene(vBoxForScene);
    primaryStage.setScene(scene);
    primaryStage.setMinHeight(400);
    primaryStage.setMinWidth(340);
    primaryStage.setAlwaysOnTop(true);
    primaryStage.show();
    circle1.requestFocus();
}

}

另一方面,这个代码应该做同样的事情,完美地工作

This code on the other hand, which is supposed to do the same thing, works perfectly

public class CircleDraggingSample extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
    final double RADIUS=10;
    Pane pane = new Pane();
    pane.setPrefHeight(300);
    pane.setPrefWidth(300);
    Circle circle1 = new Circle(RADIUS);
    circle1.setCenterX(30);
    circle1.setCenterY(30);

    Circle circle2 = new Circle(RADIUS);
    circle2.setCenterX(100);
    circle2.setCenterY(100);

    Line line = new Line();

    line.endXProperty().bind(circle2.centerXProperty());
    line.endYProperty().bind(circle2.centerYProperty());

    line.startXProperty().bind(circle1.centerXProperty());
    line.startYProperty().bind(circle1.centerYProperty());

    pane.getChildren().addAll(circle1, circle2, line);

    circle2.setOnMouseDragged(e -> {
        circle2.setCenterX(e.getX());
        circle2.setCenterY(e.getY());
    });

    circle1.setOnMouseDragged(e -> {
        circle1.setCenterX(e.getX());
        circle1.setCenterY(e.getY());
    });

    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();
}
}


推荐答案

甚至虽然你已经发布了一个例子,但我宁愿告诉你一个方法,一般来说它是如何完成的。有几种方法,这是有效的方法:

Even though you have posted an example, I'd rather show you a way with mine how it is done in general. There are several ways, this is one that works:

public class DragNodes extends Application {

    public static List<Circle> circles = new ArrayList<Circle>();

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

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        Circle circle1 = new Circle( 100, 100, 50);
        circle1.setStroke(Color.GREEN);
        circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.3));

        Circle circle2 = new Circle( 200, 200, 50);
        circle2.setStroke(Color.BLUE);
        circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));

        Line line = new Line();
        line.setStrokeWidth(20);

        // binding
        line.startXProperty().bind(circle1.centerXProperty());
        line.startYProperty().bind(circle1.centerYProperty());
        line.endXProperty().bind(circle2.centerXProperty());
        line.endYProperty().bind(circle2.centerYProperty());

        MouseGestures mg = new MouseGestures();
        mg.makeDraggable( circle1);
        mg.makeDraggable( circle2);
        mg.makeDraggable( line);

        root.getChildren().addAll(circle1, circle2, line);

        primaryStage.setScene(new Scene(root, 1024, 768));
        primaryStage.show();
    }



    public static class MouseGestures {

        class DragContext {
            double x;
            double y;
        }

        DragContext dragContext = new DragContext();

        public void makeDraggable( Node node) {
            node.setOnMousePressed( onMousePressedEventHandler);
            node.setOnMouseDragged( onMouseDraggedEventHandler);
            node.setOnMouseReleased(onMouseReleasedEventHandler);
        }

        EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {

                if( event.getSource() instanceof Circle) {

                    Circle circle = ((Circle) (event.getSource()));

                    dragContext.x = circle.getCenterX() - event.getSceneX();
                    dragContext.y = circle.getCenterY() - event.getSceneY();

                } else {

                    Node node = ((Node) (event.getSource()));

                    dragContext.x = node.getTranslateX() - event.getSceneX();
                    dragContext.y = node.getTranslateY() - event.getSceneY();

                }
            }
        };

        EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {

                if( event.getSource() instanceof Circle) {

                    Circle circle = ((Circle) (event.getSource()));

                    circle.setCenterX( dragContext.x + event.getSceneX());
                    circle.setCenterY( dragContext.y + event.getSceneY());

                } else {

                    Node node = ((Node) (event.getSource()));

                    node.setTranslateX( dragContext.x + event.getSceneX());
                    node.setTranslateY( dragContext.y + event.getSceneY());

                }

            }
        };

        EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {

            }
        };

    }

}

它显示了拖动圆并绑定另一个节点(线),以便在拖动圆圈时也可以修改它。您也可以单独拖动该行,这是一个节点,并以不同的方式处理。

It shows how to drag circles and bind another node (the line) so that it gets modified as well when you drag the circles. You can also drag the line separately which is a Node and handled differently.

如果您仍有问题,请告诉我。

In case you still got problems let me know.

作为一般说明,始终建议将其添加到节点以了解发生的事件:

As a general note, it's always advisable to add this to a node in order to understand which events happen:

 node.addEventFilter(Event.ANY, e -> System.out.println( e));

然后在屏幕上执行操作时检查控制台输出。

and then check the console output while you do something on screen.

关于您的主要问题:您不能将Fill设置为null。在这种情况下,click事件将不会被注册。您应该使用Color.TRANSPARENT。您可以使用上述方法验证事件差异。

Regarding your main problem: You mustn't set Fill to null. In that case the click event won't get registered. You should use Color.TRANSPARENT instead. You can verify the event difference with the above mentioned method.

这篇关于JavaFX Circle对象未正确注册鼠标事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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