java - 使用 Javafx 中的 ui 组件为图形编辑器创建自定义形状

标签 java javafx java-2d

我正在开发一个个人图形编辑器项目,我想创建类似流程图的图形以自动生成代码。我的第一个想法是CanvasGraphicsContext ,但事实证明它太复杂了,因为我必须手动绘制所有内容。所以我已经切换到Shape .

基本上,每个节点都是一个Shape其上有其他标准 ui 组件,例如 Label , ChoiceBox由于每个节点代表一个程序函数,我想使用这些 ui 组件来选择函数的输入。

我正在用 StackPane 做一些实验,一个Rectangle在后台有一些Label结束了:

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. StackPane始终位于 Pane 的左上角即使我已经设置了Rectangle的坐标与 setXsetY ,如何绝对定位?
  3. StackPane正确的方法是什么?

谢谢。

最佳答案

the getLayoutBounds().getWidth() and getLayoutBounds().getHeight() always return zero, so I cannot resize the rectangle according the size of labels, how can I get the real size of vbox?

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

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

但是,我建议摆脱 updateSize() 方法并将矩形边界与 RectanglePane 边界绑定(bind),这样您就不必担心基础形状的边界更新。

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

The StackPane is always in the top-left corer of Pane even I have set the coordinates of Rectangle with setX and setY, how can I position it absolutely?

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

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

Is StackPane the right approach?

据我了解您的要求,如果您正在寻找一种布局来在下面放置一个 Shape 并在其上面放置您的自定义布局,我认为 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);
  }
}

关于java - 使用 Javafx 中的 ui 组件为图形编辑器创建自定义形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53111731/

相关文章:

java - 如何处理JavaFX的线程模型和大数据变化

java - 如何获取一个点经过的点?

java - 在 JPanel 上显示所有绘制的形状

java - Netbeans MySQL 连接 - 与 jdbc 无关

java - 如何将方法调用到要使用的公共(public)静态类中?

java异常: connection reset by peer: socket write error

java - 混合像素(半透明)的更有效方法?

java - 设置 Log4jContextSelector 的属性有什么不同吗

java - 通过 Scene Builder 的 ComboBox 项目?

JavaFX 组合框图像