简体   繁体   English

JavaFX - 添加ScrollPane弹出窗口,当用户单击它时关闭该弹出窗口

[英]JavaFX - Adding a ScrollPane popup which closes when user clicks out of it

My title is badly worded because my problem is very hard to describe, so I drew an image for it: 我的标题措辞严厉,因为我的问题很难描述,所以我为它绘制了一个图像:

在此输入图像描述

I have an ImageView object which represents a pile of cards (not poker cards but just used them as an example). 我有一个ImageView对象,代表一堆牌(不是扑克牌,但只是用它们作为例子)。 When this image view is clicked, I need a window to popup that features a ScrollPane and shows them all the card objects that are in the linked list. 单击此图像视图时,我需要一个弹出窗口,其中包含ScrollPane并向其显示链接列表中的所有卡对象。 When the user clicks anywhere outside of the window (and later on, any right mouse button click) the scrollpane window needs to close. 当用户单击窗口外的任何位置(稍后,单击鼠标右键)时,需要关闭滚动窗格窗口。

Ways that I have already tried: 我已经尝试过的方法:

  • Scene with APPLICATION_MODAL. APPLICATION_MODAL的场景。 Then did Scene.showAndWait(). 然后做了Scene.showAndWait()。 I didn't like this method because it made another application on the user's taskbar. 我不喜欢这种方法,因为它在用户的任务栏上创建了另一个应用程序。 It also felt clunky and just bad. 它也觉得笨重而且很糟糕。

  • Changed my root pane to a StackPane, then added this Scrollpane to the stackpane when the user clicked on the deck. 将我的根窗格更改为StackPane,然后在用户单击卡座时将此Scrollpane添加到堆栈窗格。 This for some reason was really slow and seemed really obtrusive. 这出于某种原因非常缓慢,看起来非常突兀。 It was also annoying because my alternate class needed to have access to the root pane (since when it closes, it needs to go to the root StackPane and call .remove() on itself). 这也很烦人,因为我的备用类需要访问根窗格(因为当它关闭时,它需要转到根StackPane并自己调用.remove())。

Are there any other better ways to accomplish this? 有没有其他更好的方法来实现这一目标? My application is going to have many of these piles and so this framework needs to work very well. 我的应用程序将拥有许多这些堆,所以这个框架需要很好地工作。

I would still propose to open a new Stage with some restrictions to solve your issues with this approach. 我仍然建议开设一个新的Stage有一些限制来解决你的问题。

You can use the initOwner property of the Stage to have another Stage as owner, therefore no other icon will appear on the taskbar. 您可以使用StageinitOwner属性将另一个Stage作为所有者,因此任务栏上不会显示任何其他图标。

You can use the initStyle property with TRANSPARENT or UNDECORATED StageStlye , this will ensure that only the content is visible. 您可以将initStyle属性与TRANSPARENTUNDECORATED StageStlye ,这将确保只有内容可见。

And in the end you can use the focusedProperty to check whether the Stage lost focus to close it. 最后,您可以使用focusedProperty来检查Stage是否失去焦点以关闭它。

Example

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);

            Button b = new Button("Open deck");
            b.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    Stage popupStage = new Stage();

                    popupStage.initOwner(primaryStage);
                    popupStage.initStyle(StageStyle.UNDECORATED);
                    Scene sc = new Scene(new ScrollPane(), 300, 300);
                    popupStage.setScene(sc);

                    popupStage.focusedProperty().addListener(new ChangeListener<Boolean>() {

                        @Override
                        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue,
                                Boolean newValue) {
                            if(!newValue)
                                popupStage.close();

                        }
                    });

                    popupStage.show();

                }
            });

            root.setCenter(b);


            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

It is also possible of course to not open it in a new Stage , but draw a ScrollPane inside the current Stage which overlaps the content of the Stage using for example an AnchorPane or Group as root, but the first solution has the advantage that you are not bound to the dimensions of main Stage (the popup can have any size that you want). 也有可能,当然在新打不开Stage ,但画ScrollPane当前内部Stage 重叠的内容Stage使用例如AnchorPane为根,但第一个解决方案的优点是你没有绑定主Stage的尺寸(弹出窗口可以有你想要的任何尺寸)。

You can achieve this with a low level system hook that catches the mouse events. 您可以使用捕获鼠标事件的低级系统挂钩来实现此目的。

http://kra.lc/blog/2016/02/java-global-system-hook/ or https://github.com/kwhat/jnativehook/releases http://kra.lc/blog/2016/02/java-global-system-hook/https://github.com/kwhat/jnativehook/releases

I hope that is what you needed, otherwise i got your question wrong. 我希望这就是你需要的,否则我的问题就错了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM