如何在StackPane(JavaFX)中显示窗格时收听?

时间:2015-11-03 20:05:03

标签: events javafx rendering listener stackpanel

所以这是我的问题。在JavaFX中,我创建了一个StackPane,并在其中添加了各种其他窗格。结果如下图所示。当我点击下面的按钮时,使用" toFront()"方法。我想在所有Panes上创建监听器,无论何时它们出现在前面都会触发。 我试过用

pane.sceneProperty().addListener((obs, oldValue, newValue) -> {});

但在我的情况下不起作用,因为窗格已经是StackPane的子窗口,因此已经在场景中。

我想在这里实现的是在窗格/节点实际渲染到场景时监听。据我所知,前窗格后面的堆栈窗格中的窗格不会被渲染。

此致 约翰尼拉

http://localhost:8090/assets/bundle.js

1 个答案:

答案 0 :(得分:1)

  

据我了解,前窗格后面的堆栈窗格中的窗格不会被渲染。

这不是真的。堆栈窗格中的窗格以与子列表中的位置对应的z顺序呈现;换句话说,它们一个在另一个上面呈现,列表中的第一个元素位于堆栈的底部,最后一个元素位于顶部。如果它们都是不透明的并且都填满了整个堆栈窗格,那么用户只能看到最后一个。

您可以将一个绑定放在一起,用于跟踪堆栈窗格列表中的最后一项(即前面的节点)

ObjectBinding<Node> frontLayer = Bindings.valueAt(stack.getChildren(), 
    Bindings.size(stack.getChildren()).subtract(1));

SSCCE:

import java.util.Random;
import java.util.stream.IntStream;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class StackPaneReorderTest extends Application {

    private final Random rng = new Random();

    @Override
    public void start(Stage primaryStage) {
        StackPane stack = new StackPane();
        IntStream.rangeClosed(1, 10).mapToObj(this::createPane).forEach(stack.getChildren()::add);
        Button button = new Button("Change");
        button.setOnAction(e -> 
            stack.getChildren().get(rng.nextInt(stack.getChildren().size() - 1)).toFront());
        BorderPane root = new BorderPane(stack, null, null, button, null);
        BorderPane.setAlignment(button, Pos.CENTER);
        BorderPane.setMargin(button, new Insets(10));

        ObjectBinding<Node> frontLayer = Bindings.valueAt(stack.getChildren(), 
            Bindings.size(stack.getChildren()).subtract(1));
        frontLayer.addListener((obs, oldLayer, newLayer) ->  
            System.out.println(newLayer.getId() + " moved to front"));

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Pane createPane(int i) {
        Pane pane = new StackPane();
        pane.setId("Layer "+i);
        pane.setStyle(String.format("-fx-background-color: -fx-background; -fx-background: #%x%x%x;", 
            rng.nextInt(16), rng.nextInt(16), rng.nextInt(16)));
        pane.getChildren().add(new Label("Layer "+i));
        return pane ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

请注意,对于您的特定用例,可能会有更好的解决方案来解决您的问题。例如。您可以使用BorderPane,只需使用要显示的节点调用setCenter即可。然后,BorderPane&#39; s centerProperty始终保持可见节点。还有很多其他方法可以做到这一点。