Виджеты Kivy под другими виджетами могут взаимодействовать, как это предотвратить?

#python #kivy #kivy-language

#python #kivy #kivy-язык

Вопрос:

Рассмотрим приложение, содержащее кнопку в RelativeLayout . Если какой-либо виджет, кроме кнопки, помещается поверх него, скрывая таким образом кнопку, эта кнопка и любые другие дочерние элементы RelativeLayout будут доступны для взаимодействия, даже если они не видны.

Что можно сделать, чтобы усилить эту функциональность?

Вот пример: обратите внимание, что кнопка в центре приложения по-прежнему получает события касания, несмотря на то, что она полностью скрыта:

 from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
from kivy.graphics import *
from kivy.core.window import Window
from kivy.uix.widget import Widget


class MyApp(App):
    def build(self):
        
        def btn_pressed(instance):
            print('ok')
        
        root = RelativeLayout()
        button = Button()
        root.add_widget(button)
        
        button.size_hint = (None, None)
        button.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
        button.bind(on_press=btn_pressed)
        
        layout = RelativeLayout()
        with layout.canvas:
            Color(0,0,0,1)
            Rectangle(size=(Window.size[0], Window.size[1]))
        
        root.add_widget(layout)
        
        return root

MyApp().run() ```
 

Ответ №1:

Поведение по умолчанию для большинства виджетов — разрешить дальнейшую отправку событий касания. Это контролируется возвращаемым значением on_touch_XXX() методов. True Возврат означает «не продолжать отправку», а False возврат означает «продолжить отправку». Таким образом, вы можете остановить отправку on_touch_down событий, определив пользовательский класс, который останавливает отправку. Например:

 class MyTouchBlocker(RelativeLayout):
    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            return True
        else:
            return super(MyTouchBlocker, self).on_touch_down(touch)
 

И в вашем коде вы можете заменить:

 layout = RelativeLayout()
 

с:

 layout = MyTouchBlocker()
 

Смотрите документацию.