通过标签拖动移动 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_down 和 on_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
输出
我想定制 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_down 和 on_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