代码之家  ›  专栏  ›  技术社区  ›  vesontio

在Javafx for graph editor[duplicate]中使用ui组件创建自定义形状

  •  0
  • vesontio  · 技术社区  · 6 年前

    我正在从事一个个人图形编辑器项目,我想创建流程图一样的图形自动代码生成。我的第一个想法是 Canvas GraphicsContext ,但结果太复杂了,因为我必须手动绘制所有内容。所以我换成了 Shape

    基本上,每个节点都是一个 形状 其他标准ui组件,例如 Label , ChoiceBox

    我正在做一些实验 StackPane Rectangle 在后台有一些 标签

    public class RectangleNode extends StackPane {
    
      private double x;
      private double y;
      private VBox vbox;
      private Rectangle rect;
    
      public RectangleNode(double x, double y) {
        super();
        setAlignment(Pos.CENTER);
    
        this.x = x;
        this.y = y;
    
        Label label1 = new Label("Hello world");
        Label label2 = new Label("Hello JavaFX");
    
        vbox = new VBox(label1, label2);
    
        rect = new Rectangle();
        rect.setStroke(Color.ALICEBLUE);
        rect.setStrokeWidth(2);
        rect.setX(this.x);
        rect.setY(this.y);
    
        getChildren().addAll(rect, vbox);
      }
    
      public void updateSize () {
        double width = vbox.getLayoutBounds().getWidth();
        double height = vbox.getLayoutBounds().getHeight();
        System.out.println("width vbox: " + width + "px");
        System.out.println("height vbox: " + height + "px");
    
        rect.setWidth(width + 10);
        rect.setHeight(height + 10);
    
      }
    }
    

    节点放置在 Pane 因为它提供了组件的绝对定位:

    public class StackPaneTest extends Application {
    
      public void start(Stage stage) throws Exception {
    
        Pane root = new Pane();
    
        stage.setTitle("StackPane Test");
        stage.setScene(new Scene(root, 480, 360));
        stage.show();
    
        RectangleNode pane = new RectangleNode(100, 100);
        root.getChildren().add(pane);
        pane.updateSize();
      }
    
      public static void main(String[] args) {
        launch(args);
      }
    }
    

    1. getLayoutBounds().getWidth() getLayoutBounds().getHeight() 始终返回 vbox ?
    2. 这个 总是在左上角的取样器中 窗格 矩形 具有 setX setY ,我怎样才能完全定位它?
    3. 正确的方法?

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Sai Dandem    6 年前

    getLayoutBounds().getWidth()和getLayoutBounds().getHeight() 始终返回零,因此无法根据

    在场景图中渲染边界之前,将检查边界。如果使用Platform.runLater包装方法调用,则可以获得正确的值

    Platform.runLater(()->pane.updateSize());
    

    不过,我建议您放弃updateSize()方法,将矩形边界与矩形窗格边界绑定,这样就不必担心底层形状的边界更新。

    rect.widthProperty().bind(widthProperty());
    rect.heightProperty().bind(heightProperty());
    

    堆栈窗格始终位于窗格的左上角,即使我已设置 当然?

    您正在更新矩形属性,这是不正确的。相反,您必须实际更新StackPane translateX/Y属性才能移动矩形窗格。将构造函数中的代码更新到下面。

    //rect.setX(this.x);
    //rect.setY(this.y);
    setTranslateX(this.x);
    setTranslateY(this.y);
    

    StackPane方法正确吗?

    据我所知,您的要求,如果您正在寻找一个布局放置一个形状下面和您的自定义布局上面,我认为StackPane是一个很好的选择。

        import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    import javafx.stage.Stage;
    
    public class StackPaneTest extends Application {
      public void start(Stage stage) throws Exception {
        Pane root = new Pane();
        stage.setTitle("StackPane Test");
        stage.setScene(new Scene(root, 480, 360));
        stage.show();
        root.getChildren().add(new RectangleNode(100, 100));
      }
    
      public static void main(String[] args) {
        launch(args);
      }
    }
    class RectangleNode extends Group {
      private VBox vbox;
      private Rectangle rect;
      public RectangleNode(double x, double y) {
        super();
        StackPane layout = new StackPane();
        layout.setAlignment(Pos.TOP_LEFT);
    
        Label label1 = new Label("Hello world");
        Label label2 = new Label("Hello JavaFX");
    
        vbox = new VBox(label1, label2);
        vbox.setPadding(new Insets(5));
    
        setTranslateX(x);
        setTranslateY(y);
    
        rect = new Rectangle();
        rect.setFill(Color.YELLOW);
        rect.setStrokeWidth(2);
        rect.setStroke(Color.BLACK);
        rect.widthProperty().bind(layout.widthProperty());
        rect.heightProperty().bind(layout.heightProperty());
        layout.getChildren().addAll(rect, vbox);
        getChildren().add(layout);
      }
    }