Распространение событий в Киви - PullRequest
0 голосов
/ 08 мая 2020

Я изменил этот пример в конце этого учебника немного:

#!/usr/bin/env python

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


class RootWidget(BoxLayout):

    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        self.add_widget(Button(text='button 1'))
        cb = CustomBtn()
        cb.bind(pressed=self.btn_pressed)
        self.add_widget(cb)
        self.add_widget(Button(text='button 2'))

    def btn_pressed(self, instance, pos):
        print(f'4444 RootWidget.btn_pressed, instance: {instance} pos: {pos}')


class CustomBtn(Widget):
    pressed = ListProperty([0, 0])

    def on_touch_down(self, touch):
        print(f'1111 CustomButton.on_touch_down, touch id: {id(touch)}, touch {touch}')
        if self.collide_point(*touch.pos):
            print(f'2222 CustomButton.on_touch_down, collision, self.pressed: {self.pressed}')
            self.pressed = touch.pos
            # we consumed the touch. return False here to propagate
            # the touch further to the children.
            return True
        return super(CustomBtn, self).on_touch_down(touch)

    def on_pressed(self, instance, pos):
        print(f'3333 CustomButton.on_pressed, instance: {instance} pos: {pos}')


class TestApp(App):

    def build(self):
        return RootWidget()


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

Теперь, когда я нажимаю button 1, я получаю следующее:

1111 CustomButton.on_touch_down, touch id: 140523635041336, touch <MouseMotionEvent spos=(0.1875, 0.31999999999999995) pos=(150.0, 191.99999999999997)>

Почему? Это должно быть обработано в Button(text='button 1'), нет?

Конечно, поскольку вызов collide_point обнаруживает, что это касание произошло за пределами области настраиваемой кнопки, это не имеет неприятных последствий, но почему это происходит в первую очередь ?

Затем, чтобы сделать это еще более странным, когда я нажимаю button 2, этого не происходит (т.е. ничего не печатается).

Почему (и как?) Здесь отправляются события?

Киви: 1.11.1. ОС: Debian 10 (buster) amd64 GUI: KDE Plasma. Python: 3,7.

Журнал запуска:

[INFO   ] [Logger      ] Record log in /home/user/.kivy/logs/kivy_20-05-08_16.txt
[INFO   ] [Kivy        ] v1.11.1
[INFO   ] [Kivy        ] Installed at "/home/user/projects/kvapp/venv37/lib/python3.7/site-packages/kivy/__init__.py"
[INFO   ] [Python      ] v3.7.2 (default, Feb 22 2019, 18:56:07) 
[GCC 6.3.0 20170516]
[INFO   ] [Python      ] Interpreter at "/home/user/projects/kvapp/venv37/bin/python"
[INFO   ] [Factory     ] 184 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Window      ] Provider: sdl2(['window_egl_rpi'] ignored)
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <sdl2>
[INFO   ] [GL          ] OpenGL version <b'4.6.0 NVIDIA 418.43'>
[INFO   ] [GL          ] OpenGL vendor <b'NVIDIA Corporation'>
[INFO   ] [GL          ] OpenGL renderer <b'GeForce GTX 1080 Ti/PCIe/SSE2'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60 NVIDIA'>
[INFO   ] [GL          ] Texture max size <32768>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available

1 Ответ

0 голосов
/ 08 мая 2020

События распространяются на все Widgets в Window, пока ни одно из них не остановит распространение. Методы on_touch_down() вызываются для каждого Button в порядке, обратном их добавлению, а именно:

  1. Button 2
  2. CustomBtn
  3. Button 1

Если позиция касания находится на кнопке 2, его on_touch_down() возвращает True и останавливает распространение события, поэтому ни один другой Widget не получит это событие. Вот почему нажатие кнопки 2 не приводит к печати. ​​

Когда вы нажимаете кнопку 1, кнопка 2 видит ее первой, но поскольку она не находится внутри кнопки 2, событие игнорируется и разрешается распространяться на CustomBtn. CustomBtn on_touch_down() печатает сообщение 1111, но, поскольку касание выходит за пределы CustomBtn, оно также позволяет продолжить распространение. Теперь кнопка 1 получает событие и обрабатывает его, останавливая распространение.

Когда вы нажимаете CustomBtn, кнопка 2 снова видит его первой, но позволяет продолжить распространение. Затем CustomBtn видит событие, печатает сообщение 1111, определяет, что касание находится на CustomBtn, поэтому печатается сообщение 2222, свойство pressed изменяется (в результате чего метод on_pressed() будет запущен), и также будет запущен метод bound btn_pressed(). Затем распространение останавливается (возвращением True), поэтому кнопка 1 никогда не видит это событие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...