简体   繁体   中英

Kivy on Raspberry: Cursor is outside of window

I am developing a GUI on my RaspberryPi 3 using Python3 and Kivy 1.11.0dev. The GUI is working, it is running in fullscreen after start (as far a I know since Kivy 1.9.x it is not possible to run a Kivy app as a window) and the mouse cursor is visible. The only problem now is that the user can move the mouse out of the visible area if he goes too far to the left, right, up or down. If this happens, it is difficult to get the cursor back to the visible area.

I tried a lot to prevent that or to take the cursor back to window automatically but without success. From similar posts I tried things like this:

Window.bind(on_cursor_leave=self.on_leave)

def on_leave(self, *args):
    if self.hold:
    print('Cursor leaved Window')
    # call api calls here

I also tried to grab the mouse

Window.bind(grab_mouse=self.on_leave)

Does anybody have a solution for putting the cursor back to the visible area after leaving or to set a border where the cursor can't leave?

EDIT: Maybe this output helps:

[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  

Solution

  1. In the constructor __init__() , bind on_cursor_leave event to a callback method eg cursor_leave() .
  2. Use Window.grab_mouse() inside cursor_leave() method. Please refer to example for details.

Snippet

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)

Window » grab_mouse()

 grab_mouse() 

Grab mouse - so won't leave window

Note

This feature requires the SDL2 window provider.

Example

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

Output

IMG01

Okay I solved the Problem. It's not my favorite solution but it works:

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

The cursor is moved back when he leaves the window.

At this time my approach is:

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

So if the cursor leaves the window

Window.grab_mouse()

is called everytime but without any effect... Is there a way to set the cursor back to window when he leaves the allowed area?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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