首页 > 解决方案 > 当鼠标光标在窗口上方时,如何使我的 python-kivy 窗口成为焦点?

问题描述

python 3.7.8
kivy 2.0.0

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

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

我无法用 python-kivy 复制它。

Window.on_cursor_enter(do_action())

当光标进入窗口时不会触发。

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())

pass在kivy源中背负着a 。这就解释了为什么它不起作用。

我认为真正的更正将来自对ctypes.windll.user32...setFocus 的调用...类似的东西,但我是 Python 爱好者,我对此的理解是有限的。

标签: pythonckivywindowctypes

解决方案


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

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

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()

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

The only line of code inside the update func and the window_callback func will fired when the mouse is hover on the window (i.e. like when the mouse leaves and moves back to the app window, the window_callback will be fired) then I use pyautogui to do a mouse click by itself so that the window can be focused by itself. This way, the kivy app window can be focused when the mouse moves back to the window.

Moreover, according to this stackoverflow answer, the SLD2 on desktop app can hide the window but to restore / show it. It can scroll even when the app window is not focused (I tested!)


推荐阅读