Raspberry 上的 Kivy:光标在 window 之外
Kivy on Raspberry: Cursor is outside of window
我正在使用 Python3 和 Kivy 1.11.0dev 在我的 RaspberryPi 3 上开发一个 GUI。 GUI 正在运行,它在启动后 运行 全屏显示(据我所知,自 Kivy 1.9.x 不可能 运行 Kivy 应用程序作为 window) 并且鼠标光标可见。现在唯一的问题是,如果用户向左、向右、向上或向下移动太远,则可能会将鼠标移出可见区域。如果出现这种情况,就很难让光标回到可见区域。
我尝试了很多方法来防止这种情况发生或自动将光标移回 window 但没有成功。在类似的帖子中,我尝试了这样的事情:
Window.bind(on_cursor_leave=self.on_leave)
def on_leave(self, *args):
if self.hold:
print('Cursor leaved Window')
# call api calls here
我也试过抢鼠标
Window.bind(grab_mouse=self.on_leave)
有没有人有办法在离开后将光标放回可见区域,或者在光标不能离开的地方设置边框?
编辑:也许这个输出有帮助:
[INFO ] [Logger ] Record log in /home/pi/.kivy/logs/kivy_18-07-30_8.txt
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO ] [Kivy ] v1.11.0.dev0, git-0471549, 20180720
[INFO ] [Python ] v3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1]
[INFO ] [KivyMD ] KivyMD version: 0.1.2
[INFO ] [Factory ] 194 symbols loaded
[INFO ] [Text ] Provider: sdl2
[INFO ] [Window ] Provider: egl_rpi
[INFO ] [GL ] Using the "OpenGL ES 2" graphics system
[INFO ] [GL ] Backend used <gl>
[INFO ] [GL ] OpenGL version <b'OpenGL ES 2.0'>
[INFO ] [GL ] OpenGL vendor <b'Broadcom'>
[INFO ] [GL ] OpenGL renderer <b'VideoCore IV HW'>
[INFO ] [GL ] OpenGL parsed version: 2, 0
[INFO ] [GL ] Shading version <b'OpenGL ES GLSL ES 1.00'>
[INFO ] [GL ] Texture max size <2048>
[INFO ] [GL ] Texture max units <8>
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[INFO ] [GL ] NPOT texture support is available
xclip version 0.12
Copyright (C) 2001-2008 Kim Saunders et al.
Distributed under the terms of the GNU GPL
[INFO ] [Clipboard ] Provider: xclip
[INFO ] [CutBuffer ] cut buffer support enabled
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [HIDInput ] Read event from </dev/input/event0>
[INFO ] [ProbeSysfs ] device match: /dev/input/event1
[INFO ] [HIDInput ] Read event from </dev/input/event1>
[INFO ] [Base ] Start application main loop
[INFO ] [HIDMotionEvent] using <b'MLK USB Composite Device\x00 '>
[INFO ] [HIDMotionEvent] using <b'MLK USB Composite Device\x00
解决方案
- 在构造函数
__init__()
中,将 on_cursor_leave
事件绑定到回调方法,例如cursor_leave()
.
- 在
cursor_leave()
方法中使用 Window.grab_mouse()
。详情请参考示例
片段
class GrabMouseDemo(Label):
def __init__(self, **kwargs):
super(GrabMouseDemo, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
Window.bind(on_cursor_leave=self.cursor_leave)
grab_mouse()
Grab mouse - so won’t leave window
Note
This feature requires the SDL2 window provider.
例子
from kivy.app import App
from kivy.uix.label import Label
from kivy.core.window import Window
class GrabMouseDemo(Label):
def __init__(self, **kwargs):
super(GrabMouseDemo, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
Window.bind(on_cursor_leave=self.cursor_leave)
def mouse_pos(self, window, pos):
self.text = str(pos)
def cursor_leave(self, window):
print("cursor_leave:")
Window.grab_mouse()
class TestApp(App):
title = "Kivy Grab Mouse Demo"
def build(self):
return GrabMouseDemo()
if __name__ == "__main__":
TestApp().run()
输出
此时我的做法是:
class WSRMEGUI(BoxLayout):
...
def __init__(self, **kwargs):
super(WSRMEGUI, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
def mouse_pos(self, window, pos):
poswidth = int(pos[0])
posheight = int(pos[1])
winwidth = int(window.width)
winheight = int(window.height)
if poswidth <= 0:
Window.grab_mouse()
if poswidth > winwidth:
Window.grab_mouse()
if posheight < 0:
Window.grab_mouse()
if posheight > winheight:
Window.grab_mouse()
所以如果光标离开 window
Window.grab_mouse()
每次都调用但没有任何效果...有没有办法在他离开允许区域时将光标设置回window?
好的,我解决了问题。这不是我最喜欢的解决方案,但它有效:
# Set mouse back to visible window when leaving 1920x1080
def mouse_pos(self, window, pos):
try:
#pos_width = int(pos[0])
#pos_height = int(pos[1])
if int(pos[0]) <= 0: # Mouse outside, LEFT
window.mouse_pos = (5, int(pos[1]))
if int(pos[0]) > self.win_width: # Mouse outside, RIGHT
window.mouse_pos = (1900, int(pos[1]))
if int(pos[1]) < 0: # Mouse outside, BOTTOM
window.mouse_pos = (int(pos[0]), 20)
if int(pos[1]) > self.win_height: # Mouse outside, TOP
window.mouse_pos = (int(pos[0]), 1060)
他离开window时光标向后移动。
我正在使用 Python3 和 Kivy 1.11.0dev 在我的 RaspberryPi 3 上开发一个 GUI。 GUI 正在运行,它在启动后 运行 全屏显示(据我所知,自 Kivy 1.9.x 不可能 运行 Kivy 应用程序作为 window) 并且鼠标光标可见。现在唯一的问题是,如果用户向左、向右、向上或向下移动太远,则可能会将鼠标移出可见区域。如果出现这种情况,就很难让光标回到可见区域。
我尝试了很多方法来防止这种情况发生或自动将光标移回 window 但没有成功。在类似的帖子中,我尝试了这样的事情:
Window.bind(on_cursor_leave=self.on_leave)
def on_leave(self, *args):
if self.hold:
print('Cursor leaved Window')
# call api calls here
我也试过抢鼠标
Window.bind(grab_mouse=self.on_leave)
有没有人有办法在离开后将光标放回可见区域,或者在光标不能离开的地方设置边框?
编辑:也许这个输出有帮助:
[INFO ] [Logger ] Record log in /home/pi/.kivy/logs/kivy_18-07-30_8.txt
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO ] [Kivy ] v1.11.0.dev0, git-0471549, 20180720
[INFO ] [Python ] v3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1]
[INFO ] [KivyMD ] KivyMD version: 0.1.2
[INFO ] [Factory ] 194 symbols loaded
[INFO ] [Text ] Provider: sdl2
[INFO ] [Window ] Provider: egl_rpi
[INFO ] [GL ] Using the "OpenGL ES 2" graphics system
[INFO ] [GL ] Backend used <gl>
[INFO ] [GL ] OpenGL version <b'OpenGL ES 2.0'>
[INFO ] [GL ] OpenGL vendor <b'Broadcom'>
[INFO ] [GL ] OpenGL renderer <b'VideoCore IV HW'>
[INFO ] [GL ] OpenGL parsed version: 2, 0
[INFO ] [GL ] Shading version <b'OpenGL ES GLSL ES 1.00'>
[INFO ] [GL ] Texture max size <2048>
[INFO ] [GL ] Texture max units <8>
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[INFO ] [GL ] NPOT texture support is available
xclip version 0.12
Copyright (C) 2001-2008 Kim Saunders et al.
Distributed under the terms of the GNU GPL
[INFO ] [Clipboard ] Provider: xclip
[INFO ] [CutBuffer ] cut buffer support enabled
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [HIDInput ] Read event from </dev/input/event0>
[INFO ] [ProbeSysfs ] device match: /dev/input/event1
[INFO ] [HIDInput ] Read event from </dev/input/event1>
[INFO ] [Base ] Start application main loop
[INFO ] [HIDMotionEvent] using <b'MLK USB Composite Device\x00 '>
[INFO ] [HIDMotionEvent] using <b'MLK USB Composite Device\x00
解决方案
- 在构造函数
__init__()
中,将on_cursor_leave
事件绑定到回调方法,例如cursor_leave()
. - 在
cursor_leave()
方法中使用Window.grab_mouse()
。详情请参考示例
片段
class GrabMouseDemo(Label):
def __init__(self, **kwargs):
super(GrabMouseDemo, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
Window.bind(on_cursor_leave=self.cursor_leave)
grab_mouse()
Grab mouse - so won’t leave window
Note
This feature requires the SDL2 window provider.
例子
from kivy.app import App
from kivy.uix.label import Label
from kivy.core.window import Window
class GrabMouseDemo(Label):
def __init__(self, **kwargs):
super(GrabMouseDemo, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
Window.bind(on_cursor_leave=self.cursor_leave)
def mouse_pos(self, window, pos):
self.text = str(pos)
def cursor_leave(self, window):
print("cursor_leave:")
Window.grab_mouse()
class TestApp(App):
title = "Kivy Grab Mouse Demo"
def build(self):
return GrabMouseDemo()
if __name__ == "__main__":
TestApp().run()
输出
此时我的做法是:
class WSRMEGUI(BoxLayout):
...
def __init__(self, **kwargs):
super(WSRMEGUI, self).__init__(**kwargs)
Window.bind(mouse_pos=self.mouse_pos)
def mouse_pos(self, window, pos):
poswidth = int(pos[0])
posheight = int(pos[1])
winwidth = int(window.width)
winheight = int(window.height)
if poswidth <= 0:
Window.grab_mouse()
if poswidth > winwidth:
Window.grab_mouse()
if posheight < 0:
Window.grab_mouse()
if posheight > winheight:
Window.grab_mouse()
所以如果光标离开 window
Window.grab_mouse()
每次都调用但没有任何效果...有没有办法在他离开允许区域时将光标设置回window?
好的,我解决了问题。这不是我最喜欢的解决方案,但它有效:
# Set mouse back to visible window when leaving 1920x1080
def mouse_pos(self, window, pos):
try:
#pos_width = int(pos[0])
#pos_height = int(pos[1])
if int(pos[0]) <= 0: # Mouse outside, LEFT
window.mouse_pos = (5, int(pos[1]))
if int(pos[0]) > self.win_width: # Mouse outside, RIGHT
window.mouse_pos = (1900, int(pos[1]))
if int(pos[1]) < 0: # Mouse outside, BOTTOM
window.mouse_pos = (int(pos[0]), 20)
if int(pos[1]) > self.win_height: # Mouse outside, TOP
window.mouse_pos = (int(pos[0]), 1060)
他离开window时光标向后移动。