尝试使用JavaFX使用鼠标创建形状

尝试使用JavaFX使用鼠标创建形状,java,javafx,Java,Javafx,我正在尝试创建一个Java应用程序,它使用JavaFX允许用户通过选择单选按钮选项,然后在边框窗格区域中单击并拖动来创建形状 到目前为止,我在正确的轨道上。我遇到的问题是如何正确定位它们。我希望有人能帮我弄清楚为什么这些形状没有在我期望的地方被创造出来 目前,我创建的第一个形状被放置在HBox的左上角,我在BorderPane的中心部分有这个形状,无论我从哪里单击开始创建。拖动鼠标似乎可以根据光标精确地调整长方体的大小 随后尝试创建形状会导致在光标位置之外创建形状,拖动将调整大小,但也不会与光标

我正在尝试创建一个Java应用程序,它使用JavaFX允许用户通过选择单选按钮选项,然后在边框窗格区域中单击并拖动来创建形状

到目前为止,我在正确的轨道上。我遇到的问题是如何正确定位它们。我希望有人能帮我弄清楚为什么这些形状没有在我期望的地方被创造出来

目前,我创建的第一个形状被放置在HBox的左上角,我在BorderPane的中心部分有这个形状,无论我从哪里单击开始创建。拖动鼠标似乎可以根据光标精确地调整长方体的大小

随后尝试创建形状会导致在光标位置之外创建形状,拖动将调整大小,但也不会与光标相关

这是我的密码。我已经删除了与当前问题无关的部分,希望能让它更具可读性:

public class Main extends Application{
    public static String shapeType = "";
    public static String color = "";

    static Rectangle customRectangle = null;

    public void start(Stage mainStage) throws Exception{
        Group root = new Group();
        Scene scene = new Scene(root, 600, 400);

        BorderPane borderPane = new BorderPane();

        .....

        HBox canvas = new HBox();
        Group canvasGroup = new Group();
        canvas.getChildren().add(canvasGroup);

        canvas.setStyle("-fx-background-color: yellow");

        borderPane.setTop(shapeOptions);
        borderPane.setLeft(colorOptions);
        borderPane.setCenter(canvas);

        canvas.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if(event.getEventType() == MouseEvent.MOUSE_PRESSED && shapeType != ""){
                    switch(shapeType){
                        case "rectangle":
                            createCustomRectangle(event, color, canvasGroup);
                    }
                }
                if(event.getEventType() == MouseEvent.MOUSE_DRAGGED){
                    switch (shapeType){
                        case "rectangle":
                            editCustomRectangle(event);
                    }
                }
            }
        });

        root.getChildren().add(borderPane);
        mainStage.setScene(scene);
        mainStage.show();
    }

    public static void createCustomRectangle(MouseEvent event, String color, Group canvasGroup){
        customRectangle = new Rectangle(0, 0, 10,10);
        customRectangle.relocate(event.getX(), event.getY());

        customRectangle.setFill(Color.RED);
        canvasGroup.getChildren().add(customRectangle);
    }

    public static void editCustomRectangle(MouseEvent event){
        customRectangle.setWidth(event.getX() - customRectangle.getTranslateX());
        customRectangle.setHeight(event.getY() - customRectangle.getTranslateY());
    }

    public static void main(String[] args){
        launch(args);
    }
}
public类主扩展应用程序{
公共静态字符串shapeType=“”;
公共静态字符串颜色=”;
静态矩形customRectangle=null;
public void start(阶段主体)引发异常{
组根=新组();
场景=新场景(root,600400);
BorderPane BorderPane=新的BorderPane();
.....
HBox画布=新的HBox();
组canvasGroup=新组();
canvas.getChildren().add(canvasGroup);
canvas.setStyle(“-fx背景色:黄色”);
borderPane.setTop(形状选项);
borderPane.setLeft(颜色选项);
边框窗格。设置中心(画布);
addEventFilter(MouseEvent.ANY,neweventhandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
如果(event.getEventType()==MouseEvent.MOUSE_按下和&shapeType!=“”){
开关(形状类型){
案例“矩形”:
createCustomRectangle(事件、颜色、画布组);
}
}
if(event.getEventType()==MouseEvent.MOUSE\u拖动){
开关(形状类型){
案例“矩形”:
编辑矩形(事件);
}
}
}
});
root.getChildren().add(边框窗格);
主干。场景(场景);
show();
}
公共静态void createCustomRectangle(MouseeEvent事件、字符串颜色、组画布组){
customRectangle=新矩形(0,0,10,10);
重新定位(event.getX(),event.getY());
customRectangle.setFill(颜色:红色);
canvasGroup.getChildren().add(customRectangle);
}
公共静态void editCustomRectangle(MouseeEvent事件){
setWidth(event.getX()-customRectangle.getTranslateX());
setHeight(event.getY()-customRectangle.getTranslateY());
}
公共静态void main(字符串[]args){
发射(args);
}
}
我还想附上几张图片,让我的问题更清楚。此处尝试创建第一个形状:

这里尝试创建一个后续形状:

希望描述、代码和图像足以传达正在发生的事情。任何帮助都将不胜感激


谢谢

首先,
customRectangle.relocate(event.getX(),event.getY())显然没有做它应该做的事情。最好首先在适当的位置创建矩形

而不是:

customRectangle = new Rectangle(0, 0, 10,10);
customRectangle.relocate(event.getX(), event.getY());
试试看:
customRectangle=新矩形(event.getX(),event.getY(),10,10)

其次,它看起来像
customRectangle.getTranslateX()
customRectangle.getTranslateY()
总是返回0,所以我要看看这些方法,看看那里发生了什么。祝你好运,希望这有帮助

编辑:
与其使用
重新定位
不如尝试使用
setTranslateX()
setTranslateY()
首先,
customRectangle.relocate(event.getX(),event.getY())显然没有做它应该做的事情。最好首先在适当的位置创建矩形

而不是:

customRectangle = new Rectangle(0, 0, 10,10);
customRectangle.relocate(event.getX(), event.getY());
试试看:
customRectangle=新矩形(event.getX(),event.getY(),10,10)

其次,它看起来像
customRectangle.getTranslateX()
customRectangle.getTranslateY()
总是返回0,所以我要看看这些方法,看看那里发生了什么。祝你好运,希望这有帮助

编辑:
与其重新定位,不如尝试使用
setTranslateX()
setTranslateY()

让我们开始一次解决每个问题。首先是一个友好的建议,尝试以一种有助于读者理解其含义和身份的方式命名变量(当我第一次看到canvas变量时,我认为它是一个实际的canvas)

现在,您的布局如下所示:

BorderPane 
    TOP 
        - Something
    CENTER 
        - HBox
            - Group
                - Rectangle
                - Rectangle
                - ...
    Left
        - Something
    Bottom 
        - Something
  • HBox会获取所有可用的高度,并根据其子项计算其宽度。所以为了把所有的 BorderPane内的可用空间您需要实际指定它或将其preferredWidthProperty与 边框窗格的宽度属性

  • 从Group类的文档中可以看到:

  • 应用于组的任何变换、效果或状态都将应用于 那一组的所有孩子。这样的变换和效果将不会被忽略 但是,如果变换和 效果直接设置在该组的子对象上,这些子对象将 包含在此组的布局边界中

    因此,当您重新定位节点(实际矩形)时
    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.AnchorPane;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    import javafx.stage.Stage;
    
    public class Main extends Application {
        public static String shapeType = "";
        public static String color = "";
    
        private static Rectangle customRectangle = null;
    
        private double firstX = 0;
        private double firstY = 0;
    
        public void start(Stage mainStage) throws Exception {
    
            BorderPane mainPane = new BorderPane();
    
            HBox centerPane = new HBox();
    
            centerPane.prefWidthProperty().bind(mainPane.widthProperty());
            centerPane.prefHeightProperty().bind(mainPane.heightProperty());
    
            AnchorPane anchorPane = new AnchorPane();
    
            anchorPane.prefWidthProperty().bind(centerPane.widthProperty());
            anchorPane.prefHeightProperty().bind(centerPane.heightProperty());
    
            centerPane.getChildren().add(anchorPane);
    
            centerPane.setStyle("-fx-background-color: yellow");
    
            shapeType = "rectangle";
    
            mainPane.setCenter(centerPane);
    
            centerPane.addEventFilter(MouseEvent.ANY, new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
    
                    if (event.getEventType() == MouseEvent.MOUSE_PRESSED && shapeType != "") {
                        switch (shapeType) {
                        case "rectangle":
                            firstX = event.getX();
                            firstY = event.getY();
                            createCustomRectangle(event, color, anchorPane);
                        }
                    }
                    if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {
                        switch (shapeType) {
                        case "rectangle":
                            editCustomRectangle(event);
                            firstX = event.getX();
                            firstY = event.getY();
                        }
                    }
                }
            });
    
            Scene scene = new Scene(mainPane, 600, 400);
            mainStage.setScene(scene);
            mainStage.show();
        }
    
        public void createCustomRectangle(MouseEvent event, String color, AnchorPane canvasGroup) {
            customRectangle = new Rectangle(0, 0, 10, 10); // or just set the actual X and Y from the start
            customRectangle.relocate(event.getX(), event.getY());
    
            customRectangle.setFill(Color.RED);
            canvasGroup.getChildren().add(customRectangle);
        }
    
        public void editCustomRectangle(MouseEvent event) {
    
            double deltaX = event.getX() - firstX;
            double deltaY = event.getY() - firstY;
    
            double width = customRectangle.getWidth() + deltaX;
            double height = customRectangle.getHeight() + deltaY;
    
            customRectangle.setWidth(width);
            customRectangle.setHeight(height);
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    StackPane stackCanvas = new StackPane();
    
    stackCanvas.setStyle("-fx-background-color: yellow");
    
    borderPane.setTop(shapeOptions);
    borderPane.setLeft(colorOptions);
    borderPane.setCenter(stackCanvas);
    
    public static void createCustomRectangle(MouseEvent event, String color, StackPane stackCanvas){
        customRectangle = new Rectangle();
        StackPane.setAlignment(customRectangle, Pos.TOP_LEFT);
        stackCanvas.getChildren().add(customRectangle);
    
        customRectangle.setTranslateX(event.getX());
        customRectangle.setTranslateY(event.getY());
    
        customRectangle.setFill(Color.RED);
    }