当前位置: 首页 > 知识库问答 >
问题:

JavaFX Circle对象未正确注册鼠标事件

江天宇
2023-03-14

我希望用户能够拖动并移动窗格周围的圆圈。圆圈似乎没有(几乎)记录任何鼠标事件(如最后定义的)。我有一个空窗格的完全相同的代码,它工作得很好。如果我改变

circle1.setOnMouseDragged

paneForCircles.setOnMouseDragged

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

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();
}

}

另一方面,这段代码应该做同样的事情,工作得非常完美

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();
}
}

共有1个答案

易阳朔
2023-03-14

即使你已经发布了一个例子,我还是想用我的方法向你展示一下一般的做法。有几种方法,这是一种有效的方法:

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) {

            }
        };

    }

}

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

如果你还有问题,请告诉我。

一般来说,建议将此项添加到节点中,以了解发生了哪些事件:

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

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

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

 类似资料:
  • 我准备好为此拔掉头发了。我正在开发游戏图形用户界面,它有一个由网格单元组成的地图。 单元格网格由StackPane组成,然后由ImageView或Shapes等组成的几个层组成。 整个内容包含在GridPane中,GridPane包含BorderPane的中心元素; 我不能在底层场景中添加鼠标事件,因为所有节点都会得到它- 下面是创建堆栈的代码: 这是设置EventHandler的代码- 谢谢你的

  • 当我从SWT的树查看器中拖放时,出现了以下问题。我正在设置< code>dragSourceEvent的图像属性,例如 除了在我的树查看器节点上有一个长标签的情况之外,它工作得很好。如果我有一个很长的字符串,并从节点标题的最右边开始拖动事件,我注意到拖动图像没有被正确锚定,实际上是根据从树节点字符串的开始到树节点字符串的结束的距离偏移了X个像素。 有人有什么建议吗?Yee可能需要演示一下才能了解它

  • 我试图发出授权请求,但收到错误: 重定向URI未正确注册到DocuSign 这是我正在使用的URL: https://account-d.docusign.com/oauth/auth?response_type=code 这是我注册的重定向URI,与上面的URL匹配: 这是错误: 客户端id与integrator密钥匹配。 有什么指点吗?

  • void register_object(string object_name, object $object, array allowed methods/properties, boolean format, array block methods) This is to register an object for use in the templates. See the object s

  • 在本章中,我们将详细介绍鼠标事件及其属性。 请注意:此类事件不仅可能来自于“鼠标设备”,还可能来自于对此类操作进行了模拟以实现兼容性的其他设备,例如手机和平板电脑。 鼠标事件类型 我们已经见过了其中一些事件: mousedown/mouseup 在元素上点击/释放鼠标按钮。 mouseover/mouseout 鼠标指针从一个元素上移入/移出。 mousemove 鼠标在元素上的每个移动都会触发此

  • 鼠标事件的种类 鼠标事件指与鼠标相关的事件,继承了MouseEvent接口。具体的事件主要有以下一些。 click:按下鼠标(通常是按下主按钮)时触发。 dblclick:在同一个元素上双击鼠标时触发。 mousedown:按下鼠标键时触发。 mouseup:释放按下的鼠标键时触发。 mousemove:当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该