如何让我的 python-kivy window 在鼠标光标悬停在 window 上时成为焦点?

How do I make my python-kivy window become the focus when the mouse cursor is over the window?

python 3.7.8
kivy 2.0.0

现代程序能够在 window 中进行更改,即使应用程序的焦点不是 True。

示例:两个 windows 并排设置(Chrome 和 Excel)。我在 Chrome window 内部单击,它变成了焦点 True。然后,当我将光标移到 Excel window 时,我可以直接单击单元格或上下滚动。 Excel 中的此操作不需要我先单击 Excel window 使其成为焦点。

我无法用 python-kivy 复制它。

Window.on_cursor_enter(do_action())

当光标进入 window 时不触发。

def on_start(self):
        Window.bind(mouse_pos=self.my_callback)

def my_callback(self, instance, value):
        Window.focus = True

投掷:

File "kivy\properties.pyx", line 498, in kivy.properties.Property.__set__
   File "kivy\properties.pyx", line 1527, in kivy.properties.AliasProperty.set
   File "kivy\properties.pyx", line 1485, in kivy.properties.AliasProperty.__read_only
 AttributeError: "WindowSDL.focus" property is readonly

更新:

Window.on_cursor_enter(do_action())

在 kivy 源代码中带有 pass。这就解释了为什么它不起作用。

我认为真正的修正将来自对 ctypes.windll.user32...setFocus...之类的调用 但是我是一个Python爱好者,对此理解有限

我想我找到了解决方法,但您可能不会满意。

无论如何,这是我的解决方案:

import kivy
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.clock import Clock
from kivy.core.window import Window

import pyautogui  # for mouse click

kivy.lang.Builder.load_string("""
#:kivy 2.0.0

<Main>:
    
    ScrollView:
        do_scroll_x: True
        do_scroll_y: True
        size: root.size
        
        BoxLayout:
            size_hint: 1, None
            width: 50
            orientation: "vertical"
                
            Label:
                text: "Hello World !"
                font_size: 25
        
            Button:
                id: my_button
                text: "click me !"
                font_size: 25
                
                on_release:
                    root.button_callback()
        
""")


class Main(Widget):

    def button_callback(self):  # fired when button is clicked
        print("clicked on button !")

    def window_callback(self, instance):  # fired when cursor entered window
        Window.restore()  # seems like doesn't work
        Window.show()  # this also

        # so I do this when the mouse is hover on the window
        # import pyautogui first
        if Window.focus == False:
            pyautogui.click()  # a mouse click for focusing the window

            print(True)  # just to clarify the above line got executed

        print(f"window is focus ? {Window.focus}")  # although it may says the windows is not focused , it should be

    def update(self, dt):
        Window.bind(on_cursor_enter = self.window_callback)  # bind when on_cursor_enter


class MyKivyApp(App):

    def build(self):
        Clock.schedule_interval(Main().update, 1/60)

        return Main()


if __name__ == "__main__":
    MyKivyApp().run()

工作原理:当鼠标悬停在应用程序 window 上时,pyautogui 单击一次鼠标,以编程方式强制焦点到应用程序 window。

update func 和 window_callback func 中唯一的代码行将在鼠标悬停在 window 上时触发(即当鼠标离开并返回时到应用程序 window , window_callback 将被解雇)然后我使用 pyautogui 自己进行鼠标单击,以便 window 可以自行聚焦。这样,当鼠标移回 window.

时,kivy 应用程序 window 可以聚焦

此外,根据此 Whosebug answer ,桌面应用程序上的 SLD2 可以隐藏 window 但要恢复/显示它。即使应用程序 window 未聚焦(我测试过)它也可以滚动