这是我的代码。您可以复制粘贴并按照我下面写的内容自行查看问题。
public class MyApp extends Application {
@Override
public void start(Stage stage) throws Exception {
Scene scene = new Scene(new MyView(), 100, 150);
stage.setScene(scene);
stage.show();
}
private class MyView extends BorderPane {
MyView() {
GridPane board = new GridPane();
int size = 3;
for (int i = 0; i < size*size; i++) {
BorderPane pane = new BorderPane();
pane.setMinSize(30, 30);
pane.setBackground(new Background(new BackgroundFill(Color.RED, null, null)));
pane.setBorder(new Border(new BorderStroke(null, BorderStrokeStyle.SOLID,
null, null, null)));
pane.setOnMousePressed(e -> {
PickResult pick = e.getPickResult();
Pane selectedNode = (Pane) pick.getIntersectedNode();
selectedNode.setBackground(new Background(new BackgroundFill(Color.GREEN, null, null)));
});
board.add(pane, i / size, i % size);
}
Box box = new Box(20d, 20d, 20d);
BorderPane boardPane = new BorderPane(box, null, null, board, null);
Group root = new Group(boardPane);
SubScene scene = new SubScene(root, USE_PREF_SIZE, USE_PREF_SIZE, true, SceneAntialiasing.BALANCED);
scene.widthProperty().bind(widthProperty());
scene.heightProperty().bind(heightProperty());
setCenter(scene);
}
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
我创建了一个带有正方形网格的子场景。当我按下一个正方形时,我希望它的背景能够改变颜色。这适用于两种情况:
boardPane
或两者兼而有之。但如果我同时添加框并设置深度缓冲区,则方块不会收到该事件。相反,boardPane
收到它。我猜它与3D场景中的2D节点有关。
我尝试设置这些方法的组合:setPickOnBounds
,setDepthTest
,setMouseTransparent
但没有任何效果。
解决方案是什么?
答案 0 :(得分:1)
一旦有了3D场景,就没有二维节点这样的东西,场景图中的所有东西都有x,y和z坐标;甚至当深度缓冲区设置为false时,之前被视为2D节点的东西。
当您在根边框窗格中放置一个框时,该根边框窗格将采用该框的3D坐标。对于拾取目的,您定义的框在z坐标-10到10的3D空间中表示,因此根边界窗格被定义为-10以用于拾取目的。您放置在根边框窗格内的边框窗格没有为它们定义z坐标,因此它们最终为z坐标0,从查看器角度来看,它位于根边框窗格的后面。
因此,根边界窗格正在接收点击,但由于它现在位于与其余内容不同的z平面上,因此您定义的其他2D方形内容不会获得点击。有人可能认为根边框窗格根本没有渲染,因为它没有颜色,所以它应该被视为透明,点击只是通过子节点,但似乎不是3D拾取算法的方式JavaFX可以工作。
对于您的示例,要使所有内容都在同一Z平面中并且选择正常工作,请在for循环中添加以下行:pane.setTranslateZ(-10);
。
注意:我通过在源代码中添加以下行来调试它(向我报告了鼠标点击的目标以及每次点击的x,y,z选择结果坐标):
root.setOnMouseClicked(System.out::println);
我的建议是避免使用专为2D目的设计的布局窗格(例如边框窗格)来尝试在3D空间中布局元素。 JavaFX布局窗格实际上仅用于2D布局。要处理3D空间中的定位,您应该自己管理坐标,只需使用Group而不是从Pane派生的任何内容。至少不要尝试将3D元素添加到2D布局窗格中,因为结果可能会令人困惑(正如您所发现的那样)。
您可以通过将2D和3D项目放在不同的子场景中来进一步分离它们(这就是我认为JavaFX中的intention of the sub scene概念)。以下答案中显示了具有多个子场景的应用程序示例:How to create custom 3d model in JavaFX 8?