自定义小部件触发另一个自定义小部件的 on_touch_down 事件

custom widget triggers another custom widget's on_touch_down event

每当我按下 MyWidget 中的任何区域时,它都会触发 MyLayout class 中的第一个 MyButton 的 on_touch_down 事件。 我是 kivy 的新手,不明白为什么会这样。

<MyButton@Button>:
  background_normal: ''
  background_color: [1,0,1,1]
  font_size: "44dp"
  color:[1,1,0,1]
  border:(1,1,1,1)
  text_size:self.size

<MyWidget@Widget>:
  id:customwidget
  canvas.before:
    Color:
      rgba:0.2,0.44,0.66,1
    Rectangle:
      pos:self.pos
      size:self.size

<MyLayout>:
  MyWidget:
    id:mywidget

  MyButton:
    id:button1
    text: "User Name"
    spacing: "10dp"
    on_touch_down: button1.text= self.text + "?"
    opacity: .8

  MyButton:
    text: "ikinci"
    on_touch_down: root.export_to_png("filename.png")
  MyButton:
    text: "ucuncu"

这是python:

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.widget import Widget

class MyLayout(BoxLayout):
    pass

class KivyApp(App):
    def build(self):
        return MyLayout()

if __name__ == "__main__":
    KivyApp().run()

Python代码

  1. 创建一个 class MyButton() 并实现 on_touch_down() 方法来检查触摸与我们的小部件的碰撞。

代码段 - Python 代码

class MyButton(Button):

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            print("\tMyButton.on_touch_down:")
            if self.text == 'User Name':
                self.text= self.text + "?"
            elif self.text == 'ikinci':
                App.get_running_app().root.export_to_png("filename.png")
            return True
        return super(MyButton, self).on_touch_down(touch)

kv 文件

  1. 将动态 class <MyButton@Button>: 重命名为 class 规则,<MyButton>:
  2. MyButton:
  3. 中删除所有 on_touch_down:

片段 - kv 文件

<MyButton>:
    background_normal: ''
    background_color: [1,0,1,1]
    font_size: "44dp"
    color:[1,1,0,1]
    border:(1,1,1,1)
    text_size:self.size
...
    MyButton:
        id:button1
        text: "User Name"
        spacing: "10dp"
        opacity: .8

    MyButton:
        text: "ikinci"

    MyButton:
        text: "ucuncu"

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:

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

输出

on_touch 事件不特定于任何小部件,而是传播到您的所有小部件。见 documentation. If you only want your Button to respond, you probably want to use on_pressor on_release events instead (See button behavior).