对于第一个问题,关于在滚动新文本项后可以注意到的“跳转”:
深入挖掘后code https://github.com/vedrm/Issues_Javafx/tree/master/BoundingBoxBug,我注意到UIPane3D
has a VBox textPane
包含不同的文本节点。每次updateContent
被调用时,它会尝试添加一个文本节点,但它会检查垂直盒子的高度始终低于窗格的高度,否则该节点将被删除:
for (Text textNode : infoTextValues) {
textPane.getChildren().add(textNode);
textPane.autosize();
if (textPane.getHeight() > getHeight()) {
textPane.getChildren().remove(textNode);
textPane.autosize();
break;
}
}
虽然这基本上是正确的,但是当您向场景添加节点时,您无法获得textPane.getHeight()
立即,因为它还没有被布置,你必须等到下一个脉冲。这就是为什么下次滚动时,高度是正确的并且边界框放置得很好。
强制布局并获得正确高度的一种方法textNode
是通过强制 css 和布局传递:
for (Text textNode : infoTextValues) {
textPane.getChildren().add(textNode);
// force css and layout
textPane.applyCss();
textPane.layout();
textPane.autosize();
if (textPane.getHeight() > getHeight()) {
textPane.getChildren().remove(textNode);
textPane.autosize();
break;
}
}
注意:
这个方法[applyCss
] 通常不需要直接调用,但可以与Parent.layout()
在下一个脉冲之前或场景不在舞台中时调整节点大小。
对于第二个问题,关于将文本添加到 3D 形状的不同解决方案。
事实上,将 (2D) 文本放置在 3D 形状之上非常困难,并且需要复杂的数学运算(顺便说一句,这在项目中做得非常好)。
有一种替代方法可以避免直接使用 2D 节点。
正是在之前的question https://stackoverflow.com/questions/48618329/how-to-add-text-to-each-face-of-a-box-javafx,我“写入”到图像中,后来我将其用作 3D 形状的材质漫反射贴图。
内置 3DBox
将相同的图像放入每张脸上,所以这是行不通的。我们可以实现 3D 棱镜,或者我们可以利用CuboidMesh
FXyz3D 的节点library https://github.com/FXyz/FXyz.
更换Box
in UIPaneBoxGroup
:
final CuboidMesh contentShape;
UIPane3D displaypane = null;
PhongMaterial shader = new PhongMaterial();
final Color pColor;
public UIPaneBoxGroup(final double pWidth, final double pHeight, final double pDepth, final Color pColor) {
contentShape = new CuboidMesh(pWidth, pHeight, pDepth);
this.pColor = pColor;
contentShape.setMaterial(shader);
getChildren().add(contentShape);
addInfoUIPane();
}
并添加generateNet
method:
private Image generateNet(String string) {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
Label label5 = new Label(string);
label5.setFont(Font.font("Consolas", FontWeight.BLACK, FontPosture.REGULAR, 40));
GridPane.setHalignment(label5, HPos.CENTER);
grid.add(label5, 3, 1);
double w = contentShape.getWidth() * 10; // more resolution
double h = contentShape.getHeight() * 10;
double d = contentShape.getDepth() * 10;
final double W = 2 * d + 2 * w;
final double H = 2 * d + h;
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(d * 100 / W);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(w * 100 / W);
ColumnConstraints col3 = new ColumnConstraints();
col3.setPercentWidth(d * 100 / W);
ColumnConstraints col4 = new ColumnConstraints();
col4.setPercentWidth(w * 100 / W);
grid.getColumnConstraints().addAll(col1, col2, col3, col4);
RowConstraints row1 = new RowConstraints();
row1.setPercentHeight(d * 100 / H);
RowConstraints row2 = new RowConstraints();
row2.setPercentHeight(h * 100 / H);
RowConstraints row3 = new RowConstraints();
row3.setPercentHeight(d * 100 / H);
grid.getRowConstraints().addAll(row1, row2, row3);
grid.setPrefSize(W, H);
grid.setBackground(new Background(new BackgroundFill(pColor, CornerRadii.EMPTY, Insets.EMPTY)));
new Scene(grid);
return grid.snapshot(null, null);
}
现在所有2D相关代码都可以删除(包括displaypane
),并在滚动事件后获取图像:
public void refreshBomUIPane() {
Image net = generateNet(displaypane.getText());
shader.setDiffuseMap(net);
}
在哪里UIPane3D
:
public String getText() {
return infoTextKeys.stream().collect(Collectors.joining("\n"));
}
我还删除了边界框以获得这张图片:
我没有考虑可以添加到 VBox 的文本节点数量、字体大小,也没有考虑避免在每个滚动条上生成图像的策略:只有当文本发生变化时才应该这样做。因此,当前的方法相当慢,但可以显着改进,因为每个框只有三个可能的图像。