【问题标题】:Kivy how to give all objects same basic functionalityKivy 如何赋予所有对象相同的基本功能
【发布时间】:2019-04-24 12:19:34
【问题描述】:

假设我创建了一个名为 MyButton 的自定义 Button 类。我希望所有创建的 MyButton 在按下时播放相同的声音。但我也想为特定按钮添加不同的功能,例如我想要一些按钮来更改标签文本,但我也希望它们播放那个声音。有没有办法通过继承来做到这一点,这样我就不必记住我必须为每个创建的按钮添加播放声音功能?

编辑:假设我有一个 MyButton 类声明如下:

class MyButton(Button):

    def generic_function_for_all_buttons(self):
        print('GENERIC FUNCTION')

现在,当我尝试在代码中的其他位置创建 MyButton 时,如下所示:

class TestClass(BoxLayout):
    def __init__(**kwargs):
        self.buttons = []
        self.set_layout()

    def button_action(self,button):
        button.generic_function_for_all_buttons()
        print(button.text)

    def set_layout(self):
        for i in range(0,100):
            button = MyButton(text=i)
            button.on_press = functools.partial(button_action, button)
            self.buttons.append(button)
            self.add_widget(button)

这不是可运行的代码,只是我想要实现的演示。现在,每次我从 TestClass 中按下 MyButton 时,它都会根据按下的按钮打印 GENERIC FUNCTION 和 0-99 之间的数字。但是我必须添加 button.generic_function_for_all_buttons() 行,如果可能的话我想避免它。如果这 100 个按钮中的每一个都有自己不同的操作,如下所示:

def action_1(self,button):
    button.generic_function_for_all_buttons()
    print('1')
def action_2(self,button):
    button.generic_function_for_all_buttons()
    print('2')
def action_3(self,button):
    button.generic_function_for_all_buttons()
    print('3')
...

那个 button.generic_function_for_all_buttons() 是我想要避免的 100 行代码。我认为它必须以某种方式通过继承成为可能,例如我将 on_press 方法添加到 MyButton 类,如下所示:

class MyButton(Button):

    def on_press(self):
        print('GENERIC FUNCTION')

但它只是忽略它。

【问题讨论】:

    标签: python inheritance button kivy


    【解决方案1】:

    解决方案

    • class MyButton 中实现on_touch_down 方法
    • 使用collide_point()函数检查碰撞

    片段

    class MyButton(Button):
        def on_touch_down(self, touch):
            if self.collide_point(*touch.pos):
                print('GENERIC FUNCTION')
                print(f"MyButton.text={self.text}")
                return True    # consumed touch and stop propagation / bubbling
            return super(MyButton, self).on_touch_down(touch)
    
    
    class TestClass(GridLayout):
        def __init__(self, **kwargs):
            super(TestClass, self).__init__(**kwargs)
            self.cols = 20
            self.buttons = []
            self.set_layout()
    
        def set_layout(self):
            for i in range(0,100):
                button = MyButton(text=str(i))
                self.buttons.append(button)
                self.add_widget(button)
    

    Kivy » Touch event basics

    默认情况下,触摸事件被调度到所有当前显示的 小部件。这意味着无论是否发生,小部件都会接收到触摸事件 是否在他们的物理区域内。

    ...

    为了提供最大的灵活性,Kivy 调度 所有小部件的事件,并让它们决定如何对它们做出反应。 如果您只想响应小部件内的触摸事件,您 只需检查:

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            # The touch has occurred inside the widgets area. Do stuff!
            pass
    

    输出

    【讨论】:

    • 是的,我也得到了这个解决方案,但我不确定这是否是最好的方法。在我看来,这似乎是一种真正应该以不同方式完成的事情的解决方法。如果没有人提出更好的答案,我会对此感到满意并将其标记为已回答。
    【解决方案2】:

    我将创建一个名为 MyButton 的基类,并创建从 MyButton 继承的子按钮类。

    然后使用继承和多态,您可以在所有子按钮中保持属性和方法(例如声音)相同,但具有不同的标签,而无需为每个子按钮具有唯一的属性。

    多态性还允许您遍历所有子项,因为属性具有相同的名称。

    请参阅链接的文章更多地描述这一点:

    https://www.pythonspot.com/polymorphism/

    【讨论】:

    • 我明白你想说什么,但我认为它不能解决我的问题。我知道我可以在 MyButton 中声明一个方法(让我们称之为 play_sound),然后可以从 MyButton 的子级访问它,但仍然存在我必须记住每次调用该函数的问题。因此,每次创建 MyButton 的新子项时,我都必须创建一个 on_press 动作,并在其中调用 self.play_sound() 函数。这是我想在我的项目中避免的大量复制粘贴代码。
    • 你能发布一个你正在做的代码示例吗?
    • 用我的意思的例子编辑了我原来的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多