繁体   English   中英

Kivy:如何处理从 ModalView 的 on_touch_down 方法触发的触摸事件

[英]Kivy: how to handle touch events triggered from on_touch_down method of ModalView

有没有办法做到这一点,当我的ModalView / Popup小部件处于活动状态但它后面的任何按钮都不会被触发时?

下面是一个模态视图/弹出窗口小部件的示例,它将通知用户他们输入了不正确的内容。 我希望用户能够单击任意位置,ModalView 将消失。 问题是当这个 ModalView 可见时,后台的按钮仍然处于活动状态。

在这种情况下,BaseBoxLayout 顶部有一个标签,底部有一个按钮。 我点击按钮触发 ModalView/popup。 如果用户点击顶部,ModalView/popup 就会消失——正如我的 on_touch_down 方法所设计的那样。

但是,如果用户单击下半部分的任意位置(当 ModalView/popup 已经触发时),则 ModalView/popup 将被删除,但随后又被添加,因为后台按钮仍然处于活动状态。

我该如何防止这种情况?

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.modalview import ModalView

KV = '''
Screen:
  canvas.before:
    Color:
      rgb: [127/255,160/255,100/255]
    Rectangle:
      pos: self.pos
      size: self.size
  BaseBoxLayout:
    orientation: "vertical"
    Label:
      text: "BaseBoxLayout "
    Button:
      text: "Ok button"
      on_press: self.parent.call_popup()

<CustomPopup>
  BoxLayout:
    Label:
      text: "You can do this!"
'''

class BaseBoxLayout(BoxLayout):
  def __init__(self,**kwargs):
    super().__init__(**kwargs)

  def call_popup(self):
    print('created popup')
    self.popup = CustomPopup()
    self.popup.open()


class CustomPopup(ModalView):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)

  def on_touch_down(self,touch):
    print('removed popup')
    self.parent.remove_widget(self)


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

if __name__ == '__main__':
  MainApp().run()

由于 kivy 在调度触摸事件方面为您提供了最大的灵活性,您可以根据需要决定和实现它。

让我们考虑一下您在这种情况下可能遇到的一些典型情况。

  1. 只要您按下屏幕(窗口)上的任何位置(对应于on_touch_down事件),您的ModalView (我称之为弹出窗口)就需要被关闭。 但是此时您不希望任何底层小部件干扰。 在这里,这意味着您不想在小部件树的下方分派触摸事件。 您可以通过从方法on_touch_down 返回True来做到这一点,该方法将消化事件并阻止它进一步传播。
    def on_touch_down(self,touch):
        self.parent.remove_widget(self)
        return True
  1. 您希望像以前一样关闭弹出窗口,但也不想覆盖任何默认行为。 调用超类方法。 这比 1 更可取。
    def on_touch_down(self,touch):
        self.parent.remove_widget(self)
        return super().on_touch_down(touch)
  1. 也许您的弹出窗口不会覆盖整个窗口。 在这种情况下,您希望仅当触摸在其物理边界内时才将其关闭,否则不会。 按照 1 或 2 进行。但如果触摸超出其物理边界怎么办? 返回True以消化事件。 如果您自己不处理,请调用super (但请记住,除非您将auto_dismiss设置为 False,否则它将关闭弹出窗口)。
    def on_touch_down(self,touch):
        if self.collide_point(*touch.pos):
            self.parent.remove_widget(self)
        # Otherwise stop propagation and digest.
        return True
        # Or for default handling.
#       return super().on_touch_down(touch)

可能有可数的(如果不是无限的)没有。 您可以在这里面对的情况。 所以最好停在这里。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM