重点关注时如何使JavaFX Popup出现在最前面?

时间:2019-01-14 11:09:46

标签: java user-interface javafx javafx-11

我的应用程序中有一些JavaFX Popup。并且,当这些弹出窗口中的任何一个出现时,无论它在Window.getWindows()中的索引如何,我都需要将其置于所有其他弹出窗口之上。

我尝试调用类似toFront的方法,但是它不在Popup类中。我也曾尝试在Popup中更改焦点Window.getWindows()的索引,但这也没有用,因为我不知道如何交换ObservableList中两个元素的索引。 / p>

例如

比方说,我有两个分别称为Popupp1的{​​{1}}和节点p2n1,分别用于移动这些弹出窗口,因此,每当拖动n2时,n1应该放在顶部,而当拖动p1时,n2应该放在顶部。

这是我的最小示例:

p2

那么这个问题的解决方案是什么?

2 个答案:

答案 0 :(得分:2)

出于某种原因,我不了解,toFront / back仅在舞台上实现,而不是在其父类上实现,即使Window中已经可以使用实际的协作者来管理堆栈了:

阶段执行:

/**
 * Bring the {@code Window} to the foreground.  If the {@code Window} is
 * already in the foreground there is no visible difference.
 */
public void toFront() {
    if (getPeer() != null) {
        getPeer().toFront();
    }
}

getPeer()是Window中的程序包专用方法,它返回内部类TKStage。因此,如果您被允许变脏(因为访问内部类并且必须通过反射进行访问-都带有通常的大声“当心”!),那么:

protected void toFront(Popup popup) {
    // use your favorite utility method to invoke a method  
    TKStage peer = (TKStage) FXUtils.invokeGetMethodValue(Window.class, popup, "getPeer");
    if (peer != null) {
        peer.toFront();
    }
}

需要导出/打开javafx.graphics中未导出的程序包-编译器和运行时错误将为您提供指导(无论如何我的上下文都进行了很大的调整,因此不确切知道该添加了哪些内容)

答案 1 :(得分:0)

这是具有阶段性的解决方案,尽管您讨厌这样的功能,但您讨厌拥有多个阶段的想法,这是我发现的唯一解决方案。如果您决定坚持将它们放在后台,那也很酷。解决您也可能遇到阶段困境的一个想法是使用一个阶段队列在使用时删除,如果所有阶段都显示,则在隐藏阶段时添加一个新阶段,发送到队列末尾

public class Example extends Application {


    public void applyTo(Pane node, Stage parent, Stage primaryStage){

        final double[] dragDelta = new double[2];

        node.setOnMousePressed(e -> {
            dragDelta[0] = parent.getX() - e.getScreenX();
            dragDelta[1] = parent.getY() - e.getScreenY();
            //code to bring parent Popup to front
        });

        node.setOnMouseDragged(e -> {
            parent.setX(e.getScreenX() + dragDelta[0]);
            parent.setY(e.getScreenY() + dragDelta[1]);
            primaryStage.requestFocus();
        });

        node.setOnMouseReleased(event -> {
            primaryStage.requestFocus();
        });
    }


    @Override
    public void start(Stage primaryStage) throws Exception{

        Button b1 = new Button("Open p1");
        Button b2 = new Button("Open p2");

        HBox n1 = new HBox(new Label("This is p1"));
        HBox n2 = new HBox(new Label("This is p2"));
        n1.setMinSize(200, 120);
        n2.setMinSize(200, 120);
        n1.setStyle("-fx-background-color: blue; -fx-background-radius: 4px;");
        n2.setStyle("-fx-background-color: red; -fx-background-radius: 4px;");
        n1.setAlignment(Pos.CENTER);
        n2.setAlignment(Pos.CENTER);

        Stage p1 = new Stage(StageStyle.UNDECORATED);
        Stage p2 = new Stage(StageStyle.UNDECORATED);
        p1.setAlwaysOnTop(true);
        p2.setAlwaysOnTop(true);
        p1.setScene(new Scene(n1));
        p2.setScene(new Scene(n2));

        applyTo(n1, p1, primaryStage);
        applyTo(n2, p2, primaryStage);

        b1.setOnAction(event -> {
            if(!p1.isShowing()) {
                p1.show();
                primaryStage.requestFocus();
            }
            else
                p1.hide();
        });

        b2.setOnAction(event -> {
            if(!p2.isShowing()) {
                p2.show();
                primaryStage.requestFocus();
            }
            else
                p2.hide();
        });



        HBox root = new HBox(10, b1, b2);
        root.setAlignment(Pos.CENTER);

        primaryStage.setScene(new Scene(root, 500, 200));
        primaryStage.show();
    }

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

}