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

在Javafx图形编辑器中使用ui组件创建自定义形状[复制]

慕冠宇
2023-03-14

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

基本上,每个节点都是一个Shape,上面有其他标准的ui组件,如LabelChoiceBox等。因为每个节点都代表一个程序函数,所以我想使用这些ui组件来选择函数的输入。

我正在用StackPane做一些实验,背景是一个矩形,上面有一些标签s:

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

  }
}

节点放置在窗格中,因为它提供组件的绝对定位:

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. 堆叠窗格始终位于窗格的左上角,即使我用setXsetY设置了矩形的坐标,我如何绝对定位它?
  3. StackPane是正确的方法吗

谢谢

共有1个答案

丰赞
2023-03-14

getLayoutBounds().getWidth()和getLayoutBounds().getHeight()始终返回零,因此我无法根据标签的大小调整矩形的大小,如何获得vbox的实际大小?

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

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

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

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

StackPane始终位于窗格的左上角,即使我用setX和setY设置了矩形的坐标,我如何绝对定位它?

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

//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);
  }
}
 类似资料:
  • 我正在用JavaFX制作一个2D游戏,当检测到冲突时,我得到的结果相当不准确,因为玩家精灵被设置为矩形的填充,因此没有预期的边框。有没有办法让我自己的形状尽可能准确? 我的另一个想法是检查碰撞的像素是否透明,然后如果它是,则不会结束游戏。有谁知道一种方法可以获得碰撞像素的坐标,以便从那里我可以使用PixelReader进行检查? 如果有人知道更好的方法,请告诉我! 谢谢,伊森

  • 我不是JavaFX的资深程序员,想请教一下。如何在JavaFX中为按钮制作或设置不同的形状?默认情况下,按钮具有这些圆角矩形形状。我想做一个按钮形状像下面的图片,一个L形按钮。 我已经谷歌了这个话题很多次,但仍然没有找到解决办法。 你能帮助我吗?

  • 绘制自定义形状-扇形 感谢群友 墨明棋妙 309764601@qq.com 提供功能思路和源码 目前cesium的entity里面是没有直接绘制扇形的形状的,当时在网上搜索的时候,在官方的google group里面有人明确说明是没有的,然后需要自己重载Geometry,再重新打包。。。 这,略麻烦,然后墨明棋妙兄弟就自己写了一个函数来进行绘制,最终提供了源码,感谢感谢 思路比较简单,如下: 1.

  • 我已经浏览了android中的MPAndroidChart库:https://github.com/PhilJay/MPAndroidChart 它非常强大的库,用于在android中实现Graph和Chart。 我必须显示条形图,如下所示: 我所取得的成就是: 问题是,我是否可以将这些条自定义为如上图所示。i、 e.圆角形状?

  • 创建蒙版 您可以使用以下任何方法为合成中的每个图层创建一个或多个蒙版。 使用形状工具或钢笔工具绘制一个路径。绘制蒙版路径类似于绘制形状路径。(请参阅通过使用形状工具进行拖动创建形状或蒙版和使用钢笔工具创建贝塞尔曲线形状或蒙版。) 在“蒙版形状”对话框中通过数字指定蒙版路径的大小。(请参阅用数字创建矩形或椭圆蒙版。) 通过将形状的路径复制到“蒙版路径”属性将形状路径转换为蒙版路径。 将运动路径转换为

  • 问题内容: 我喜欢创建一个看起来像这个图像的java jframe。我已经创建了 具有不同形状(例如三角形,圆形,多边形和一些疯狂的 形状)的jframe。但是问题是很难[99%不可能]创建 这样的图像。我怎么能像这样的jframe。我用这段代码来创建 形状的窗口。 现在我可以将此图像转换为形状。然后设置setshapes。任何想法吗?还是 有办法使jframe的完全透明和jlable(使图像 完