【问题标题】:Kivy: undesirable behavior of custom mouse cursor when crossing left or top edge of app windowKivy:自定义鼠标光标在越过应用程序窗口的左边缘或上边缘时的不良行为
【发布时间】:2018-12-20 05:44:17
【问题描述】:

我想在 kivy 中制作一个自定义鼠标光标。 这是我目前拥有的:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.scatter import Scatter
from kivy.core.window import Window
#Window.show_cursor = False

KV = """
FloatLayout
    BoxLayout
        MyTextInput
    MyMouse


<MyTextInput>:
    font_size: 40
    text: 'Some text'

<MyMouse>:
    mouse_im_size: mouse_im.size
    auto_bring_to_front: True

    do_rotation:False
    do_scale:False
    do_translation_y:False

    Image
        id: mouse_im
        size: 100, 100 / self.image_ratio
        source: 'cursor-pink.png'

"""

class MyTextInput(TextInput):
    pass

class MyMouse(Scatter):
    def __init__(self, **kwargs):
        Window.bind(mouse_pos=self.on_mouse_pos)
        super(MyMouse, self).__init__(**kwargs)

    def on_touch_down(self, *touch):
        return

    def on_mouse_pos(self, *args):
        x,y = args[1]
        self.pos = [x,y-self.mouse_im_size[1]]


class MyApp(App):
    def build(self):
        self.root = Builder.load_string(KV)

MyApp().run()

问题是当我将鼠标移出应用程序的左边缘或上边缘时,光标图像仍保留在应用程序内,我希望鼠标图像消失,就像我将鼠标移出右边缘或下边缘时一样.

问题似乎是on_mouse_pos() 仅在鼠标位于窗口内时才有效。

found a way 获取鼠标在窗口外时的位置,但我不知道如何在我的任务中使用它。也许有更好的方法来做到这一点。

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    您可以通过使用Window 事件on_cursor_enteron_cursor_leave 并使用opacity 属性使光标可见/不可见来完成此操作:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.button import Button
    from kivy.uix.textinput import TextInput
    from kivy.uix.scatter import Scatter
    from kivy.core.window import Window
    #Window.show_cursor = False
    
    KV = """
    FloatLayout
        BoxLayout
            MyTextInput
        MyMouse
            id: themouse
    
    
    <MyTextInput>:
        font_size: 40
        text: 'Some text'
    
    <MyMouse>:
        mouse_im_size: mouse_im.size
        auto_bring_to_front: True
    
        do_rotation:False
        do_scale:False
        do_translation_y:False
    
        Image
            id: mouse_im
            size: 100, 100 / self.image_ratio
            source: 'cursor-pink.png'
    
    """
    
    class MyTextInput(TextInput):
        pass
    
    class MyMouse(Scatter):
        def __init__(self, **kwargs):
            Window.bind(mouse_pos=self.on_mouse_pos)
            Window.bind(on_cursor_leave=self.on_cursor_leave)
            Window.bind(on_cursor_enter=self.on_cursor_enter)
            super(MyMouse, self).__init__(**kwargs)
    
        def on_touch_down(self, *touch):
            return
    
        def on_mouse_pos(self, *args):
            x,y = args[1]
            self.pos = [x,y-self.mouse_im_size[1]]
    
        def on_cursor_leave(self, *args):
            App.get_running_app().root.ids.themouse.opacity = 0
    
        def on_cursor_enter(self, *args):
            App.get_running_app().root.ids.themouse.opacity = 1
    
    
    class MyApp(App):
        def build(self):
            self.root = Builder.load_string(KV)
    
    MyApp().run()
    

    我将themouse id 添加到MyMouse 小部件以完成此操作。

    【讨论】:

    • 这是一个不错的选择,但理想情况下,我希望与将光标移动到右侧或底部边缘时的行为完全相同,您可能会注意到光标“逐渐”消失了
    • 我认为这是由于您定位鼠标的方式。尝试将self.pos = [x,y-self.mouse_im_size[1]] 更改为self.pos = [x-self.mouse_im_size[0]/2.0, y-self.mouse_im_size[1]/2.0]
    • 然后触摸区域被移动(到光标图像的中心,但我需要它像往常一样位于箭头的尖端)。
    【解决方案2】:

    这是另一种方法,但它需要在您的基本布局周围设置边框:

    from kivy.app import App
    from kivy.clock import Clock
    from kivy.lang import Builder
    from kivy.uix.button import Button
    from kivy.uix.textinput import TextInput
    from kivy.uix.scatter import Scatter
    from kivy.core.window import Window
    #Window.show_cursor = False
    
    KV = """
    FloatLayout
        canvas.before:
            Color:
                rgba: (1, 0, 0, 1)
            Rectangle:
                size: self.size
                pos: self.pos
        FloatLayout
            id: mainlayout
            size_hint: (None, None)
            #pos: (50, 50)
            #pos_hint: {'center_x': 0.5, 'center_y': 0.5}
            canvas.before:
                Color:
                    rgba: (0, 1, 0, 1)
                Rectangle:
                    size: self.size
                    pos: self.pos
            BoxLayout
                size_hint: (1.0, 0.2)
                pos_hint: {'center_x': 0.5, 'top': 1.0}
                MyTextInput
            StencilView:
                size_hint: (1.0, 1.0)
                pos_hint: {'x': 0, 'y': 0}
                MyMouse
                    id: themouse
    
    
    <MyTextInput>:
        font_size: 40
        text: 'Some text'
    
    <MyMouse>:
        mouse_im_size: mouse_im.size
        auto_bring_to_front: True
    
        do_rotation:False
        do_scale:False
        do_translation_y:False
    
        Image
            id: mouse_im
            size: 100, 100 / self.image_ratio
            source: 'cursor-pink.png'
    
    """
    
    class MyTextInput(TextInput):
        pass
    
    class MyMouse(Scatter):
        def __init__(self, **kwargs):
            Window.bind(mouse_pos=self.on_mouse_pos)
            super(MyMouse, self).__init__(**kwargs)
    
        def on_touch_down(self, *touch):
            return
    
        def on_mouse_pos(self, *args):
            x,y = args[1]
            self.pos = [x,y-self.mouse_im_size[1]]
    
    class MyApp(App):
        def build(self):
            self.mainlayout = None
            self.mymouse = None
            self.root = Builder.load_string(KV)
            Window.bind(size=self.do_size)
            Clock.schedule_once(self.do_size)
    
        def do_size(self, *args):
            if self.mainlayout is None:
                self.mainlayout = self.root.ids.mainlayout
            if self.mymouse is None:
                self.mymouse = self.root.ids.themouse
    
            self.mainlayout.size = (self.root.width - 2.0 * self.mymouse.mouse_im_size[0], self.root.height - 2.0 * self.mymouse.mouse_im_size[1])
            self.mainlayout.pos = self.mymouse.mouse_im_size
    
    MyApp().run()
    

    这使用 StencilView 将光标的绘图剪辑到 man 布局的内部。

    【讨论】:

    • 我想有人会觉得这很有用,但这绝对不适合我的任务,我的应用中不会有寄宿生。
    猜你喜欢
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多