首页 > 解决方案 > 如何正确地将回调绑定到 Python Kivy 库中循环中的每个元素

问题描述

我有以下代码:

from functools import partial

class DishesScreen(Screen):

    def on_pre_enter(self):
        Window.size = (800, 800)
    
        for i in range(10):
            self.layout.add_widget(AsyncImage(source='<url>', allow_stretch=True,
                                              size_hint_y=None, size_hint_x=None))
            dish_widget = self.get_params_layout()
            dish_widget.bind(on_touch_down=partial(self.move, data[i]))
            self.layout.add_widget(dish_widget)

    def get_params_layout(self):
        params_layout = BoxLayout(orientation='vertical', size_hint_y=None, spacing=10, padding=10)
        return params_layout

    def move(self, *args):
        # some actions here
        pass

我想要做的是move()使用特定于列表中每个元素的参数调用函数BoxLayout

如果我单击第二个元素 - 我希望move()使用特定于第二个元素的参数执行函数,如果我单击第 7 个元素 - 我希望move()使用特定于第 7 个元素的参数执行函数等。

相反,无论我单击哪个元素,该move()函数都会执行 10 次,每次它使用从最后一个元素开始到第一个元素结束的元素的参数。

我认为这是因为我添加dish_widgetlayout: self.layout.add_widget(dish_widget)。这意味着当我点击某个地方时,实际上我点击了layout,程序会执行所有 10 个move()附加到layout. 但无法弄清楚如何改变这种行为。我只需要调用一个move()函数——唯一一个附加到BoxLayout我在列表中单击的元素 ( ) 上的函数。有人可以帮忙吗?

更新:

这是标记:

<DishesScreen>:
    layout: layout
    ScrollView:
        do_scroll_x: False
        do_scroll_y: True
        GridLayout:
            id: layout
            cols:2
            size_hint: 1, None
            height: self.minimum_height
            spacing: 5, 5

标签: pythoncallbackscopekivyclosures

解决方案


你们所有人都Widgets将收到该touch事件。从小部件文档

on_touch_down(), on_touch_move(), on_touch_up() 不做任何形式的碰撞。如果您想知道触摸是否在您的小部件内部,请使用 collide_point()。

因此,您的move()方法必须进行碰撞测试以确定 是否在touchthat 的范围内Widget。像这样的东西:

def move(self, data, source, touch):
    if source.collide_point(*touch.pos):
        print('move', data)
        return True  # stop the bubbling of this touch to other widgets

推荐阅读