Javafx 弹出窗口在失去焦点时不会隐藏在其他应用程序后面

2022-01-20 00:00:00 user-interface popup java javafx-2

所以我的问题,如标题中所述(有点),是关于 Javafx(即 2.2)弹出窗口的某些方面的行为.大多数时候,你会得到一个弹出窗口,然后给它一个窗口来充当它的父级,你给它一些场景,它往往会相对独立地行动.

So my question, as stated (sort of) in the title, is about the behaviour in some respects of the Javafx (namely 2.2) Popup. Most of the time, you get a popup, and you give it a window to act as it's parent, you give it some scene, and it tends to act relatively independently.

这一切都很好,但是,就我而言,我需要一个弹出窗口,当事件发生时,它可以将自身锚定到特定位置的特定阶段(窗口).然后,该弹出窗口将在窗口消失时消失(最小化,屏幕外,等等),在它会移动时移动,并且在所有本质和功能上,它是窗口的物理扩展,只是具有自定义形状.

This is all fine, however, in my case, I needed a popup that would anchor itself to a particular stage (window), at a particular location, when an event happened. That popup would then, in turn, disappear when the window disappeared (minimize, off screen, whatever), moved when it would, and in all essence and functionality, be a physical extension of the window, just with a custom shape.

当然,这有很多细微差别,而且大多数情况下,一切都很好.我似乎唯一想不通的是,通常在像 Windows 7 64 位这样的平台上.你打开两个程序,好吧.然后,如果程序有一点重叠,无论哪个有焦点,都会显示整个程序,而另一个给人的印象是在"另一个窗口后面".(当另一个窗口聚焦在同一个位置时,Windows 是否真的在窗口后面"渲染应用程序图形,我不确定.).通常,javafx 也很好地支持此功能.但由于某种原因,javafx 中的 Popup 类(请参阅文档 这里) 不会那样做.它总是在它所显示的任何内容之上,无一例外.为了完整起见,这是我非常简单的弹出代码(至少与显示它及其属性有关的部分):

Now of course, there are a lot of nuances with that, and everything for the most part, works great. The only thing I can't seem to figure out is that normally in a platform like Windows 7 64 bit, say. You open two programs, alright. Then if the programs are overlapping a little bit, whichever has focus gets to have the entire program displayed, whereas the other one gives the impression of being 'behind' the other window. (Whether or not windows actually renders application graphics 'behind' a window when another has focus on the same spot, I'm not sure.). Normally, javafx also supports this functionality just fine. But for some reason, The Popup class in javafx (see docs here) doesn't do that. It's always on top of whatever it's displayed with, without exception. For the point of completeness, here's my pretty straightforward popup code (at least the part pertaining to showing it and it's properties):

        Popup myPop = new Popup();
        //************************Popup Property Setter**************************
        //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
        myPop.setWidth(width);
        myPop.setHeight(initialHeight);
        myPop.setAutoHide(false);
        myPop.setAutoFix(false);
        myPop.setHideOnEscape(false);
        myPop.setX(xLocation);
        myPop.setY(yLocation);
        //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
        //**********************end of Popup Properties**************************
        myPop.getContent().add(main_anchor);
        myPop.show(FileChooserWindow.get_stage());

主锚点有一些我在myPop"弹出窗口中包含的各种组件,并且 FileChooserWindow 是一个非空父窗口,它将在此方法调用时毫无例外地打开.

main anchor has some various components i include inside of the 'myPop' popup, and FileChooserWindow is a non-null parent window that will be open at the time of this method calling without exception.

这也是我所指行为的屏幕截图.请注意 pdf 中突出显示的文本,这是我的光标当前具有焦点的位置.此外,可以在从左侧突出的 pdf 背面看到弹出窗口所锚定的窗口.

Here is a screenshot as well of the behaviour I'm referring to. Notice the highlighted text in the pdf, that is where my cursor currently has focus. Also, the window that the popup is anchored to can be seen in the back of the pdf poking out from the left.

你们可以提供的任何帮助将不胜感激.我真的希望我不必检查活动进程及其相对于弹出窗口的位置,这已经危险地接近我的知识边界,听起来像是一个完整的 PITA.

Any help you guys can give would be much appreciated. I really hope I don't have to check for active processes and their location relative to the popup, that's getting dangerously close to my knowledge border, and sounds like a total PITA.

推荐答案

所以,在玩了几天之后,我有一个粗略的解决方法,尽管它是一个完整的术语.

So, after toying with this for a few more days, I have a rough workaround, although it is a hack in the full meaning of the term.

虽然弹出窗口的行为仍然让我感到困惑,但我可以通过在它所附加的阶段添加一个 changeListener 来模拟此行为的修复(因为如果它的父窗口有焦点,我不希望弹出窗口关闭,只有当弹出窗口和它的父级有任何焦点时).

Although the popup behaviour is still mystifying me, I can simulate a fix in this behaviour by adding a changeListener to the stage to which it is attached (since I didn't want the popup to close if it's parent window had focus, only if anything BUT the popup and it's parent got focus).

查看代码如下:

FileChooserWindow.get_stage().focusedProperty().addListener(new ChangeListener<Boolean>(){
            @Override
            public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) {
                if (!newValue){
                    if(AutogenPopup.popupReturner().focusedProperty().get()){
                        AutogenPopup.popupReturner().hide();
                    }
                }else{
                    if(FileChooserController.refreshAutoPopup && FileChooserController.autoGen_flag){
                        AutogenPopup.popupReturner().show(FileChooserWindow.get_stage());
                    }
                }
            }

        });

不要介意我正在检查的那些标志,它们只是一些内部工具,以确保仅当程序处于正确状态时才会出现弹出窗口.

never mind some of those flags that I'm checking against, they are simply some internal tools to make sure that the popup only appears when the program is in the proper state.

现在,要注意一件有趣的事情.AutogenPopup.popupReturner().focusedProperty().get()当弹出窗口的父窗口失去焦点时,似乎返回 true.这对我来说是非常违反直觉的,在我看来,这甚至是一个触摸错误.现在,这并不能模拟现代操作系统的行为,其中窗口可以逐步滑入和滑出焦点,因为弹出窗口将在其父窗口失去焦点时完全消失.但是看到我的弹出窗口如何在主窗口的一侧显示额外的文本条目,这是一个可以接受的折衷方案,直到我想到更好的解决方案.(也许更好的解决方案是根本不使用弹出窗口,而是对窗口进行皮肤以弹出式方式运行).

Now, one interesting thing to note. The AutogenPopup.popupReturner().focusedProperty().get() Seemed to be returning true when the popup's parent window LOST focus. Which is quite counter-intuitive to me, and in my opinion, is even a touch buggy. Now, this does not simulate the behaviour of a modern operating system where a window can slide in and out of focus incrementally, since the popup will just completely disappear upon it's parent window losing focus. But seeing as how my popup just displays additional text entry on the side of the main window, this is an acceptable compromise until I think of a better solution. (Perhaps the better solution is not to use a popup at all, and instead skin a window to act in a popup-y fashion).

无论如何,我希望这对某人有所帮助,也许最终会有一种更细粒度的方式来控制此弹出功能.

Anyway, I hope this helps someone, maybe eventually there will be a more fine-grained way to control this popup functionality.

相关文章