从 Kivy 中的多点触摸 类 继承时确定触摸执行层次
Determining touch execution hierarchy when inheriting from multiple touch classes in Kivy
我正在尝试结合 KivyMD MDCardSwipe 和 kivy_garden drag_n_drop 的功能。 MDCardSwipe 允许您将卡片滑动到一边以显示底层小部件——在我的例子中带有垃圾桶图标和删除功能——并且 drag_n_drop 允许您四处拖动小部件以在布局中重新排序它们。理想情况下,我想要可以通过拖动重新排列的可滑动卡片。
我创建了一个 class DragCard,如下所示,它继承自 MDCardSwipe 和 DraggableObjectBehavior。当我以这种方式订购时,MDCardSwipe 功能起作用,但 DraggableObjectBehavior 不起作用。当我颠倒顺序时,MDCardSwipe 不再起作用,但 DraggableObjectBehavior 起作用。
MDCardSwipe 有一个相对较小的区域,滑动必须在该区域内开始。我希望 MDCardSwipe 在该区域内接收触摸,如果触摸在所述区域外,则将触摸传递给 DraggableObjectBehavior。
如有任何帮助,我们将不胜感激!
.py 文件:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.card import MDCardSwipe
from kivy.uix.widget import Widget
from kivy_garden.drag_n_drop import DraggableLayoutBehavior, DraggableObjectBehavior
from kivy.properties import StringProperty
class DraggableBoxLayout(DraggableLayoutBehavior, BoxLayout):
def __init__(self, **kwargs):
super().__init__(
spacer_widget = MySpacer(),
spacer_props = {'size_hint_y': None, 'height' : 150 },
**kwargs)
def compare_pos_to_widget(self, widget, pos):
if self.orientation == 'vertical':
return 'before' if pos[1] >= widget.center_y else 'after'
return 'before' if pos[0] < widget.center_x else 'after'
def handle_drag_release(self, index, drag_widget):
self.add_widget(drag_widget, index)
class DragCard(MDCardSwipe, DraggableObjectBehavior):
text = StringProperty()
def initiate_drag(self):
# during a drag, we remove the widget from the original location
self.parent.remove_widget(self)
class MySpacer(Widget):
"""Widget inserted at the location where the dragged widget may be
dropped to show where it'll be dropped.
"""
pass
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = "Cyan"
Window.size = (375, 740)
return Builder.load_file("drag.kv")
def on_start(self):
pass
if __name__ == '__main__':
MainApp().run()
.kv 文件:
#:kivy 2.0.0
BoxLayout:
orientation: 'vertical'
DraggableBoxLayout:
drag_classes: ['card']
orientation: 'vertical'
DragCard:
text: 'A'
drag_cls: 'card'
DragCard:
text: 'B'
drag_cls: 'card'
DragCard:
text: 'C'
drag_cls: 'card'
DragCard:
text: 'D'
drag_cls: 'card'
DragCard:
text: 'E'
drag_cls: 'card'
DragCard:
text: 'F'
drag_cls: 'card'
DragCard:
text: 'G'
drag_cls: 'card'
DragCard:
text: 'H'
drag_cls: 'card'
<DragCard>:
size_hint_y: None
height: 150
MDCardSwipeLayerBox:
padding: "8dp"
MDIconButton:
icon: "trash-can"
pos_hint: {"center_y": .5}
# on_release: root.delete_template()
MDCardSwipeFrontBox:
Label:
text: root.text
pos_hint: {'center_x': .5, 'center_y': .5}
halign: 'center'
valign: 'center'
font_style: 'H3'
<MySpacer>:
canvas:
Color:
rgba: [.95, .57, .26, 1]
Rectangle:
size: self.size
pos: self.pos
以下代码似乎可以执行您想要的操作。 DragCard
的 on_touch_down()
方法根据 touch
在 DragCard
上的位置调用 DraggableObjectBehavior
或 MDCardSwipe
的 on_touch_down()
方法].其他touch
方法根据touch
(由DraggableObjectBehavior
设置)的grab_current
属性决定调用哪个方法:
class DragCard(DraggableObjectBehavior, MDCardSwipe):
text = StringProperty()
def initiate_drag(self):
# during a drag, we remove the widget from the original location
self.parent.remove_widget(self)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
if touch.x > self.center_x:
return DraggableObjectBehavior.on_touch_down(self, touch)
else:
return MDCardSwipe.on_touch_down(self, touch)
def on_touch_up(self, touch):
if touch.grab_current == self:
return DraggableObjectBehavior.on_touch_up(self, touch)
else:
return MDCardSwipe.on_touch_up(self, touch)
def on_touch_move(self, touch):
if touch.grab_current == self:
return DraggableObjectBehavior.on_touch_move(self, touch)
else:
return MDCardSwipe.on_touch_move(self, touch)
我正在尝试结合 KivyMD MDCardSwipe 和 kivy_garden drag_n_drop 的功能。 MDCardSwipe 允许您将卡片滑动到一边以显示底层小部件——在我的例子中带有垃圾桶图标和删除功能——并且 drag_n_drop 允许您四处拖动小部件以在布局中重新排序它们。理想情况下,我想要可以通过拖动重新排列的可滑动卡片。
我创建了一个 class DragCard,如下所示,它继承自 MDCardSwipe 和 DraggableObjectBehavior。当我以这种方式订购时,MDCardSwipe 功能起作用,但 DraggableObjectBehavior 不起作用。当我颠倒顺序时,MDCardSwipe 不再起作用,但 DraggableObjectBehavior 起作用。
MDCardSwipe 有一个相对较小的区域,滑动必须在该区域内开始。我希望 MDCardSwipe 在该区域内接收触摸,如果触摸在所述区域外,则将触摸传递给 DraggableObjectBehavior。
如有任何帮助,我们将不胜感激!
.py 文件:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.card import MDCardSwipe
from kivy.uix.widget import Widget
from kivy_garden.drag_n_drop import DraggableLayoutBehavior, DraggableObjectBehavior
from kivy.properties import StringProperty
class DraggableBoxLayout(DraggableLayoutBehavior, BoxLayout):
def __init__(self, **kwargs):
super().__init__(
spacer_widget = MySpacer(),
spacer_props = {'size_hint_y': None, 'height' : 150 },
**kwargs)
def compare_pos_to_widget(self, widget, pos):
if self.orientation == 'vertical':
return 'before' if pos[1] >= widget.center_y else 'after'
return 'before' if pos[0] < widget.center_x else 'after'
def handle_drag_release(self, index, drag_widget):
self.add_widget(drag_widget, index)
class DragCard(MDCardSwipe, DraggableObjectBehavior):
text = StringProperty()
def initiate_drag(self):
# during a drag, we remove the widget from the original location
self.parent.remove_widget(self)
class MySpacer(Widget):
"""Widget inserted at the location where the dragged widget may be
dropped to show where it'll be dropped.
"""
pass
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = "Cyan"
Window.size = (375, 740)
return Builder.load_file("drag.kv")
def on_start(self):
pass
if __name__ == '__main__':
MainApp().run()
.kv 文件:
#:kivy 2.0.0
BoxLayout:
orientation: 'vertical'
DraggableBoxLayout:
drag_classes: ['card']
orientation: 'vertical'
DragCard:
text: 'A'
drag_cls: 'card'
DragCard:
text: 'B'
drag_cls: 'card'
DragCard:
text: 'C'
drag_cls: 'card'
DragCard:
text: 'D'
drag_cls: 'card'
DragCard:
text: 'E'
drag_cls: 'card'
DragCard:
text: 'F'
drag_cls: 'card'
DragCard:
text: 'G'
drag_cls: 'card'
DragCard:
text: 'H'
drag_cls: 'card'
<DragCard>:
size_hint_y: None
height: 150
MDCardSwipeLayerBox:
padding: "8dp"
MDIconButton:
icon: "trash-can"
pos_hint: {"center_y": .5}
# on_release: root.delete_template()
MDCardSwipeFrontBox:
Label:
text: root.text
pos_hint: {'center_x': .5, 'center_y': .5}
halign: 'center'
valign: 'center'
font_style: 'H3'
<MySpacer>:
canvas:
Color:
rgba: [.95, .57, .26, 1]
Rectangle:
size: self.size
pos: self.pos
以下代码似乎可以执行您想要的操作。 DragCard
的 on_touch_down()
方法根据 touch
在 DragCard
上的位置调用 DraggableObjectBehavior
或 MDCardSwipe
的 on_touch_down()
方法].其他touch
方法根据touch
(由DraggableObjectBehavior
设置)的grab_current
属性决定调用哪个方法:
class DragCard(DraggableObjectBehavior, MDCardSwipe):
text = StringProperty()
def initiate_drag(self):
# during a drag, we remove the widget from the original location
self.parent.remove_widget(self)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
if touch.x > self.center_x:
return DraggableObjectBehavior.on_touch_down(self, touch)
else:
return MDCardSwipe.on_touch_down(self, touch)
def on_touch_up(self, touch):
if touch.grab_current == self:
return DraggableObjectBehavior.on_touch_up(self, touch)
else:
return MDCardSwipe.on_touch_up(self, touch)
def on_touch_move(self, touch):
if touch.grab_current == self:
return DraggableObjectBehavior.on_touch_move(self, touch)
else:
return MDCardSwipe.on_touch_move(self, touch)