JavaFX 中的 Z-Order画家的算法JavaFX 中的 Z-Order
如何在 JavaFX 中设置 Z 顺序?VBox
如何在 JavaFX 中设置 Z 顺序?VBox
JavaFX中的Z顺序实际上是场景图中的顺序,例如。在场景的内容序列中(然后在组,容器等的内容中)。
所有节点还具有 toFront() 和 toBack() 函数,以帮助更改此顺序。为了更好地控制,您必须从一个位置删除节点,并将其插入序列中更高或更低的位置。
TL;DR:
场景图的顺序决定了节点的呈现顺序(Z 顺序)。
children
Parent
VBox
在 JavaFX 9+ 中,可以使用 Node#viewOrder
属性来更改节点的呈现顺序,而无需更改这些节点的布局位置。
场景图的渲染遵循:
画家的算法通过以下方式创建图像:按深度对图像中的多边形进行排序,并按从最远到最近对象的顺序放置每个多边形
“画家算法”这个名字指的是许多画家采用的技术,他们首先在较近的部分之前绘制场景的远处部分,从而覆盖远处部分的某些区域。
实际的实现可能与传统画家的算法不同,用于性能目的,也用于3D场景的深度缓冲区处理,但渲染的一般原理保持不变,并且在推理将要看到的内容和将要遮挡的内容时使用是一个很好的框架。
算法输入的渲染顺序首先是节点相对于相机的 z 坐标,然后是视图顺序(如果设置),然后是具有相同 z 坐标和未指定视图顺序的元素的子顺序。
在 JavaFX 中,Z 顺序主要由场景图的顺序决定。这个顺序是由每个子列表中的 s 的顺序决定的(递归地,深度优先)。Node
Parent
例如,以下应用程序:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
var titleLabel = new Label("Title");
var fieldLabel = new Label("Field:");
var textField = new TextField();
var hbox = new HBox(fieldLabel, textField);
var button = new Button("Action");
var root = new VBox(titleLabel, hbox, button);
var scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
生成以下场景图:
+-------------+
| |
| Window |
| |
+------|------+
|
+------|------+
| |
| Scene |
| |
+------|------+
|
+------|------+
| |
+----------- VBox ------------+
| | | |
| +------|------+ |
| | |
+-------|-----+ +------|------+ +------|------+
| | | | | |
| Label | | HBox | | Button |
| | | | | |
+-------------+ +------|------+ +-------------+
|
+---------|---------+
| |
+------|------+ +-------|-----+
| | | |
| Label | | TextField |
| | | |
+-------------+ +-------------+
有三个孩子:一个、一个和一个。如果这些子代重叠,那么它们将出现在其后代及其所有后代的后面。类似地,(及其所有后代)将呈现在 .对于 ,如果它的子项重叠,则第二个子项将呈现在 .VBox
Label
HBox
Button
Label
HBox
HBox
Button
HBox
Label
TextField
因此,如果要更改节点的 Z 顺序,则只需更改场景图的顺序即可。在单一父级的上下文中,您可以使用两种方便的方法:
Node#toBack()
:将节点移动到其父级子级列表的开头,使其呈现在该父级的其他子级后面。
Node#toFront()
:将节点移动到其父级子级列表的末尾,使其呈现在该父级的其他子级之上。
警告:许多布局(如 )使用子列表的顺序来确定其子项相对于彼此的位置。更改这些布局的子级列表的顺序除了更改渲染顺序外,还将更改子级的位置。VBox
请注意,在 FXML 中,子节点元素的声明顺序是它们在父节点的子列表中出现的顺序。
Node.viewOrder
如上面的警告中所述,更改子列表的顺序可能会产生不希望的副作用。若要避免这些副作用,可以使用 Node#viewOrder
属性。
在其父级中定义此项的呈现和选取顺序。
Node
此属性用于更改节点在其父级中的呈现和选取顺序,而无需对父级列表重新排序。例如,这可以用作实现透明度排序的更有效方法。为此,应用程序可以将每个节点的值分配给该节点与查看器之间的计算距离。
children
viewOrder
父项将按降序遍历其。这意味着一个较低的孩子将排在一个具有较高.如果两个子项具有相同的子项,则父项将按照它们在父项列表中出现的顺序遍历它们。
children
viewOrder
viewOrder
viewOrder
viewOrder
children
但是,不会更改其父级中此内容的布局和焦点遍历顺序。父项在执行布局或焦点遍历时始终按顺序遍历其列表。
viewOrder
Node
children
此属性的缺省值为 。0.0
请注意,此属性仅影响单个父项的呈现顺序。例如,在上面的示例中,您无法通过仅更改 的值来强制呈现 在 的顶部,因为 和 属于不同的父级。TextField
Button
viewOrder
TextField
Button
TextField
可以使用 从 CSS 使用 设置此属性。-fx-view-order
每个都有 、 和坐标/维度。在 2D 场景中,只有 和 值具有任何意义。但在3D场景中,坐标/维度也有意义。要获得 3D 场景,必须实例化 (or),其参数设置为 。Node
x
y
z
x
y
z
Scene
SubScene
depthBuffer
true
Scene scene = new Scene(root, width, height, true, SceneAntialiasing.BALANCED);
- 请参阅文档。
这只能在施工期间完成。之后无法更改该值。另外,请注意,该参数是可选的(即,有一个重载没有该参数,但它默认为 )。depthBuffer
SceneAntialiasing
DISABLED