通过标签拖动移动 Kivy window - Kivy,Python

Move Kivy window by label drag - Kivy, Python

我想定制 window header Kivy window。我对 kivy 很陌生,所以请提供一些事件如何运作的解释。我需要简单地将 window 移动 "moving" 标签。

首先我想知道,为什么当我点击或拖动标签时它会调用任何函数。它在 KvLang 中:

#:import main main.window

CustBoxLayout:
<CustBoxLayout>:
    orientation: 'vertical'

    Label:
        id: header
        text: 'MyApp'
        font_size: 24
        padding_x: 16
        color: self.theme_cls.primary_color

        on_touch_down: main.click
        on_touch_move: main.move

...

单击或拖动标签时没有调用任何函数。但是,如果我将 main.click 更改为例如 print('touched!') 它会起作用。

所以我创建了自己的 class:

class HeadLabel(MaterialLabel):
    def on_touch_down(self, touch):
        window.click(touch)

    def on_touch_move(self, touch):
        window.drag(touch)

这行得通。但是现在我不知道如何从 MotionEvent 事件中获取屏幕位置。这是我的 window:

的实际代码
class WindowApp(App):
    theme_cls = ThemeManager()

    def build(self):
        self.theme_cls.theme_style = 'Light'
        self.theme_cls.primary_palette = 'Purple'

        return CustBoxLayout()

    def click(self, touch):
        self.touch_x, self.touch_y = touch.spos[0], touch.spos[1]

    def drag(self, touch):
        Window.top = self.touch_y + touch.spos[0]
        Window.left = self.touch_x + touch.spos[1])

任何帮助将不胜感激。

为自定义 Label 定义一个 class 并实现 on_touch_downon_touch_move 方法。详情请参考以下范例。

Programming Guide » Input management » Touch event basics

By default, touch events are dispatched to all currently displayed widgets. This means widgets receive the touch event whether it occurs within their physical area or not.

In order to provide the maximum flexibility, Kivy dispatches the events to all the widgets and lets them decide how to react to them. If you only want to respond to touch events inside the widget, you simply check for collision.

例子

main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivymd.theming import ThemeManager


class CustomLabel(Label):

    def on_touch_down(self, touch):
        print("\nCustomLabel.on_touch_down:")

        if self.collide_point(*touch.pos):
            print("\ttouch.pos =", touch.pos)
            self.touch_x, self.touch_y = touch.spos[0], touch.spos[1]
            return True
        return super(CustomLabel, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        print("\nCustomLabel.on_touch_move:")

        if self.collide_point(*touch.pos):
            print("\ttouch.pos =", touch.pos)
            Window.top = self.touch_y + touch.spos[0]
            Window.left = self.touch_x + touch.spos[1]
            return True
        return super(CustomLabel, self).on_touch_move(touch)


class CustBoxLayout(BoxLayout):
    pass


class TestApp(App):
    theme_cls = ThemeManager()

    def build(self):
        self.theme_cls.theme_style = 'Light'
        self.theme_cls.primary_palette = 'Purple'

        return CustBoxLayout()


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

test.kv

#:kivy 1.10.0

<CustomLabel>:


<CustBoxLayout>:
    orientation: 'vertical'

    CustomLabel:
        id: header
        text: 'MyApp'
        font_size: 24
        padding_x: 16
        color: app.theme_cls.primary_color

    Button:
        text: 'Button Widget'
        font_size: 24
        padding_x: 16
        color: app.theme_cls.primary_color

输出