为什么 KivyMD on_touch_down 事件会触发多个项目?

Why is KivyMD on_touch_down event triggering multiple items?

我的 KivyMD 应用程序中有一个屏幕,其中包含项目列表。我的 objective 是根据单击的项目导航到不同的屏幕。我注意到无论我选择哪个项目,下一个屏幕都与单击的项目相关或不相关。好像是随机的。

下面是一个可重现的例子。为了简化,我删除了大部分项目并用简单的打印功能替换了导航。

当单击一个项目或“取消”按钮时,会打印多个文本,就好像我单击了屏幕上的多个元素(例如,单击项目 1 会导致“项目 3 项目 2 项目 1 “正在打印)我怀疑这就是导航不一致的原因

我觉得这很混乱。有人可以向我解释这里发生了什么吗?谢谢:)

from kivy.lang import Builder
from kivymd.app import MDApp

KV = '''
MDScreen:
    name: "screen1"         
    MDBoxLayout:
        orientation: "vertical"
        MDToolbar:
            id : tb_screen1
            title: "Select Item"
            on_touch_down:   
                app.p(self.title)
        ScrollView:
            MDList:
                OneLineListItem:
                    text: "item1"
                    on_touch_down:   
                        app.p(self.text)
                        
                OneLineListItem:
                    text: "item2"
                    on_touch_down:
                        app.p(self.text)
                          
                OneLineListItem:
                    text: "item3"
                    on_touch_down:
                        app.p(self.text)
                           
                        
        MDBoxLayout:
            MDFloatLayout:                           
                MDRectangleFlatIconButton:
                    text: "Cancel"
                    on_press:
                        app.p(self.text)

'''

class MainApp(MDApp):
    def build(self):
        return Builder.load_string(KV)

    def p(self,text):
        print(text)

MainApp().run()

这是 touch 事件处理的设计行为。 touch 事件被传递给所有小部件,每个小部件负责确定它是否应该响应 touch。扩展 ButtonBehavior 的小部件(如 OneLineListItemMDRectangleFlatIconButton)在 on_presson_release 行为中内置了该测试,因此您可以只使用 on_presson_release(而不是 on_touch_down)。

MDToolbar 没有 ButtonBehavior,因此您必须将该测试添加到 on_touch_down。你可以这样做:

    MDToolbar:
        id : tb_screen1
        title: "Select Item"
        on_touch_down:
            app.p(self.title) if self.collide_point(*args[1].pos) else False

以上 kv 代码仅在触摸点位于 MDToolbar 范围内时调用 app.p(self.title)。上面的args是kivy中的关键字(参见keywords)。 args[1]就是touchpos就是那个touch的位置。前面的 *pos 扩展为其 xy 组件(如 collide_point() 方法所期望的那样)。