如何在绘制的矩形区域上创建StackPane

时间:2015-05-18 04:22:06

标签: javafx javafx-2

我正在创建UI编辑器,为此我需要在鼠标事件上绘制UI组件。我一直坚持使用带有标题的绘图按钮。由于我在stackoverflow上搜索,我尝试使用StackPane创建带标题的Rectangle。 对于布局I,使用Group元素。问题是,当我将StackPane添加到Group时,它会显示在Group的左上角。但是,如果我只绘制矩形本身,它会显示在那个地方,我释放鼠标。 如何为StackPane实现相同的效果?

这是我的代码:

public class Main extends Application {
double startingPointX, startingPointY;
Group rectanglesGroup = new Group();
Rectangle newRectangle = null;
boolean newRectangleIsBeingDrawn = false;

// the following method adjusts coordinates so that the rectangle
// is shown "in a correct way" in relation to the mouse event
void adjustRectanglePRoperties(double startingPointX,
        double startingPointY, double endingPointX, double endingPointY,
        Rectangle givenRectangle) {
    givenRectangle.setX(startingPointX);
    givenRectangle.setY(startingPointY);
    givenRectangle.setWidth(endingPointX - startingPointX);
    givenRectangle.setHeight(endingPointY - startingPointY);

    if (givenRectangle.getWidth() < 0) {
        givenRectangle.setWidth(-givenRectangle.getWidth());
        givenRectangle.setX(givenRectangle.getX()
                - givenRectangle.getWidth());
    }

    if (givenRectangle.getHeight() < 0) {
        givenRectangle.setHeight(-givenRectangle.getHeight());
        givenRectangle.setY(givenRectangle.getY()
                - givenRectangle.getHeight());
    }
}

@Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("Drawing rectangles");
    Scene scene = new Scene(rectanglesGroup, 800, 600);
    scene.setFill(Color.BEIGE);

    scene.setOnMousePressed(e -> {
        if (newRectangleIsBeingDrawn == false) {
            startingPointX = e.getSceneX();
            startingPointY = e.getSceneY();

            newRectangle = new Rectangle();

            // a non finished rectangle has always the same color
            newRectangle.setFill(Color.SNOW); // almost white color
            //Line line = new Line(20,120,270,120);
            newRectangle.setStroke(Color.BLACK);
            newRectangle.setStrokeWidth(1);
            newRectangle.getStrokeDashArray().addAll(3.0, 7.0, 3.0, 7.0);

            rectanglesGroup.getChildren().add(newRectangle);

            newRectangleIsBeingDrawn = true;
        }
    });

    scene.setOnMouseDragged(e -> {
        if (newRectangleIsBeingDrawn == true) {
            double currentEndingPointX = e.getSceneX();
            double currentEndingPointY = e.getSceneY();

            adjustRectanglePRoperties(startingPointX, startingPointY,
                    currentEndingPointX, currentEndingPointY, newRectangle);
        }
    });

    scene.setOnMouseReleased(e->{
        if(newRectangleIsBeingDrawn == true){
            //now the drawing of the new rectangle is finished
            //let's set the final color for the rectangle

            /******************Drawing textbox*******************************/
            //newRectangle.setFill(Color.WHITE);
            //newRectangle.getStrokeDashArray().removeAll(3.0, 7.0, 3.0, 7.0);
            /****************************************************************/


            /*****************Drawing button*********************************/
            Image image = new Image("file:button.png");
            ImagePattern buttonImagePattern = new ImagePattern(image);
            newRectangle.setFill(buttonImagePattern);
            newRectangle.setStroke(Color.WHITE);
            newRectangle.getStrokeDashArray().removeAll(3.0,7.0,3.0,7.0);
            Text text = new Text("Button");
            rectanglesGroup.getChildren().remove(newRectangle);
            StackPane stack = new StackPane();

            stack.getChildren().addAll(newRectangle, text);
            rectanglesGroup.getChildren().add(stack);

            /****************************************************************/
            colorIndex++; //index for the next color to use

            //if all colors have been used we'll start re-using colors
            //from the beginning of the array

            if(colorIndex>=rectangleColors.length){
                colorIndex=0;
            }

            newRectangle=null;
            newRectangleIsBeingDrawn=false; 

        }
    });
    primaryStage.setScene(scene);
    primaryStage.show();

}

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

}

我使用OnMouseReleased事件来创建组件。

我查找了setX,setPosition或类似这样的方法,但无法在StackPane的方法中找到它们。 而且我不知道翻译方法是如何工作的。所以我没有尝试过它们来实现我的目标。

1 个答案:

答案 0 :(得分:2)

您应该阅读有关JavaFX Node的文档。

您可以通过setLayoutX(和Y)或相对来自setTranslateX(和Y)绝对定位节点,这会增加当前布局位置。

StackPane只是一个容器,在您的情况下,与您要放置在场景中的任何其他节点没有什么不同。只需创建它,设置尺寸和位置并将其放在场景中。

您的代码不起作用,所以我创建了自己的代码。以下是有关如何处理此问题的示例代码:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeLineCap;
import javafx.stage.Stage;

public class RubberBandSelectionDemo extends Application {

    CheckBox drawButtonCheckBox;

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


    Pane root;

    @Override
    public void start(Stage primaryStage) {

        root = new Pane();
        root.setStyle("-fx-background-color:white");
        root.setPrefSize(1024, 768);

        drawButtonCheckBox = new CheckBox( "Draw Button");
        root.getChildren().add( drawButtonCheckBox);

        primaryStage.setScene(new Scene(root, root.getWidth(), root.getHeight()));
        primaryStage.show();

        new RubberBandSelection(root);

    }


    public class RubberBandSelection {

        final DragContext dragContext = new DragContext();
        Rectangle rect;

        Pane group;

        public RubberBandSelection( Pane group) {

            this.group = group;

            rect = new Rectangle( 0,0,0,0);
            rect.setStroke(Color.BLUE);
            rect.setStrokeWidth(1);
            rect.setStrokeLineCap(StrokeLineCap.ROUND);
            rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6));

            group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler);
            group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler);
            group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler);

        }

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

            @Override
            public void handle(MouseEvent event) {
                dragContext.mouseAnchorX = event.getSceneX();
                dragContext.mouseAnchorY = event.getSceneY();

                rect.setX(dragContext.mouseAnchorX);
                rect.setY(dragContext.mouseAnchorY);
                rect.setWidth(0);
                rect.setHeight(0);

                group.getChildren().add( rect);

            }
        };

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

            @Override
            public void handle(MouseEvent event) {

                // get coordinates
                double x = rect.getX();
                double y = rect.getY();
                double w = rect.getWidth();
                double h = rect.getHeight();

                if( drawButtonCheckBox.isSelected()) {

                    // create button
                    Button node = new Button();
                    node.setDefaultButton(false);
                    node.setPrefSize(w, h);
                    node.setText("Button");
                    node.setLayoutX(x);
                    node.setLayoutY(y);
                    root.getChildren().add( node);


                } else {
                    // create rectangle
                    Rectangle node = new Rectangle( 0, 0, w, h);
                    node.setStroke( Color.BLACK);
                    node.setFill( Color.BLACK.deriveColor(0, 0, 0, 0.3));
                    node.setLayoutX( x);
                    node.setLayoutY( y);
                    root.getChildren().add( node);
                }


                // remove rubberband
                rect.setX(0);
                rect.setY(0);
                rect.setWidth(0);
                rect.setHeight(0);

                group.getChildren().remove( rect);


            }
        };

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

            @Override
            public void handle(MouseEvent event) {

                double offsetX = event.getSceneX() - dragContext.mouseAnchorX;
                double offsetY = event.getSceneY() - dragContext.mouseAnchorY;

                if( offsetX > 0)
                    rect.setWidth( offsetX);
                else {
                    rect.setX(event.getSceneX());
                    rect.setWidth(dragContext.mouseAnchorX - rect.getX());
                }

                if( offsetY > 0) {
                    rect.setHeight( offsetY);
                } else {
                    rect.setY(event.getSceneY());
                    rect.setHeight(dragContext.mouseAnchorY - rect.getY());
                }
            }
        };

        private final class DragContext {

            public double mouseAnchorX;
            public double mouseAnchorY;


        }
    }
}

这是一张图片:

enter image description here

演示显示橡皮筋选择,允许您绘制选择矩形。释放鼠标按钮时,将绘制矩形或按钮,具体取决于左上角的“绘制按钮”复选框选项。如果您想绘制StackPane,只需在鼠标释放处理程序中相应地更改代码。

当然,如果您想直接绘制组件而不是橡皮筋,只需将橡皮筋选择代码中的矩形与e交换。 G。一个按钮。这里只是Button绘图代码,只需在上面的示例中替换它。

public class RubberBandSelection {

    final DragContext dragContext = new DragContext();
    Button button;

    Pane group;

    public RubberBandSelection( Pane group) {

        this.group = group;

        button = new Button();
        button.setPrefSize(0, 0);

        group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler);
        group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler);
        group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler);

    }

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

        @Override
        public void handle(MouseEvent event) {
            dragContext.mouseAnchorX = event.getSceneX();
            dragContext.mouseAnchorY = event.getSceneY();

            button.setLayoutX(dragContext.mouseAnchorX);
            button.setLayoutY(dragContext.mouseAnchorY);
            button.setPrefWidth(0);
            button.setPrefHeight(0);

            group.getChildren().add( button);

        }
    };

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

        @Override
        public void handle(MouseEvent event) {

            // get coordinates
            double x = button.getLayoutX();
            double y = button.getLayoutY();
            double w = button.getWidth();
            double h = button.getHeight();

            // create button
            Button node = new Button();
            node.setDefaultButton(false);
            node.setPrefSize(w, h);
            node.setText("Button");
            node.setLayoutX(x);
            node.setLayoutY(y);
            root.getChildren().add( node);

            // remove rubberband
            button.setLayoutX(0);
            button.setLayoutY(0);
            button.setPrefWidth(0);
            button.setPrefHeight(0);

            group.getChildren().remove( button);


        }
    };

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

        @Override
        public void handle(MouseEvent event) {

            double offsetX = event.getSceneX() - dragContext.mouseAnchorX;
            double offsetY = event.getSceneY() - dragContext.mouseAnchorY;

            if( offsetX > 0)
                button.setPrefWidth( offsetX);
            else {
                button.setLayoutX(event.getSceneX());
                button.setPrefWidth(dragContext.mouseAnchorX - button.getLayoutX());
            }

            if( offsetY > 0) {
                button.setPrefHeight( offsetY);
            } else {
                button.setLayoutY(event.getSceneY());
                button.setPrefHeight(dragContext.mouseAnchorY - button.getLayoutY());
            }
        }
    };

    private final class DragContext {

        public double mouseAnchorX;
        public double mouseAnchorY;


    }
}