Пользовательское распространение событий Kivy

Я делаю графический интерфейс Python/Kivy для подключенного к Интернету устройства. Происходит много синхронизации, так как устройство использует для связи метод WAMP pub/sub. Проблема в том, что я не знаю, как распространять пользовательские события, такие как on_connect, on_disconnect и т. Д., Из приложения kivy в соответствующий виджет kivy.

Вот то, что я сейчас имею, обнажив до минимума для лучшей читабельности, а также фиктивную кнопку подключения, прикрепленную для имитации происходящего события подключения.

MyApp.py:

from kivy.app import App
from kivy.config import Config
from MainPage import MainPage
from AboutPage import AboutPage
from MainContainer import MainContainer

class MyApp(App):
    def build(self):
        self.container = MainContainer()
        self.register_event_type('on_connect')
        return self.container

    def on_session(self, session):
        print("session connected!")
        self.session = session
        self.dispatch('on_connect')

    def on_connect(self, *args):
        pass
MyApp().run()

my.kv:

#:kivy 1.10.1
#:import CardTransition kivy.uix.screenmanager.CardTransition
#:set menucolor1 0, 0.603, 0.784, 1
#:set menucolor2 0, 0.203, 0.384, 1
#:set backgroundcolor 0.95, 0.95, 0.95, 1

<MenuButton@Button>:
    size_hint_y: None
    height: 50
    markup: True

<MenuSpacer@Label>:
    size_hint_y: None
    height: 3
    canvas.before:
        Color:
            rgba: menucolor1
        Rectangle:
            pos: self.pos
            size: self.size
<MainPage>:
    canvas.before:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    name: 'main_screen'
    Label:
        color: menucolor1
        text: "Hi I'm Main Screen"

<AboutPage>:
    canvas:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    name: 'about_screen'
    Label:
        color: menucolor1
        text: "Hi I'm About Screen"


<MainContainer>:
    manager: manager
    canvas:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        size: root.size
        orientation: 'horizontal'
        BoxLayout:
            orientation: 'vertical'
            width: 150
            size_hint_x: None
            MenuButton:
                text: '[b]Main[/b]'
                on_press: root.switch_to('main_screen')
            MenuSpacer:
            MenuButton:
                text: "[b]About[/b]"
                on_press: root.switch_to('about_screen')
            MenuSpacer:
            MenuButton:
                text: "[b]DummyConnect[/b]"
                on_press: root.dummyconnect()
            Widget:
                canvas.before:
                    Color:
                        rgba: menucolor1
                    Rectangle:
                        pos: self.pos
                        size: self.size
        ScreenManager:
            id:manager
            transition: CardTransition(direction='right',mode='push',duration=0.2)
            MainPage:
            AboutPage:

MainContainer.py

from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.app import App

class MainContainer(Widget):

    manager = ObjectProperty(None)

    def __init__(self, **kwargs):
        self.register_event_type('on_connect')
        super(MainContainer,self).__init__(**kwargs)
        print(self.children)

    def switch_to(self,name):
        self.manager.current = name

    def on_connect(self, *args):
        print("hello there")

    def dummyconnect(self):
        App.get_running_app().on_session("dummysession")

MainPage.py

from kivy.uix.screenmanager import Screen

class MainPage(Screen):
    pass

AboutPage.py

from kivy.uix.screenmanager import Screen

class AboutPage(Screen):
    pass

Поэтому в основном я хотел бы, чтобы событие on_connect, отправляемое в MyApp, распространялось на MainPage и AboutPages, в настоящее время только MainContainer определил on_connect, но даже это не срабатывает.

Я думаю, я мог бы сделать это, распространяя это сам для всех детей в каждом виджете, но мне нужно было бы внедрить это также для всех box-макетов, экранных менеджеров и экранов? Я думаю, что есть лучший способ сделать это, но я еще не нашел его.

Любая помощь приветствуется!

1 ответ

Решение

Решение

Распространение on_connect на все экраны, т.е. MainPage и AboutPage. Пожалуйста, обратитесь к примеру для деталей.

  1. Добавлены идентификаторы для MainPage и AboutPage
  2. Привязать к ним обратные вызовы. Когда событие отправляется, ваши обратные вызовы будут вызываться с параметрами, относящимися к этому конкретному событию.
  3. return True, указывая на то, что мы поглотили прикосновение и не хотим, чтобы оно распространялось дальше.
  4. Удалены коды в App (main.py) и добавлены некоторые в MainContainer.py

Заметка

Я прокомментировал return True показать распространение события. Попробуйте раскомментировать return True чтобы показать распространение остановлено.

обрывки

MainContainer

def __init__(self, **kwargs):
    super(MainContainer, self).__init__(**kwargs)
    self.register_event_type('on_connect')
    print(self.children)
    self.bind(on_connect=self.ids.main_page.on_connect)
    self.bind(on_connect=self.ids.about_page.on_connect)
...
def on_connect(self, *args):
    print("\nMainContainer.on_connect()")
    print("hello there")
    # return True   # indicating that we have consumed the touch and don’t want it to propagate any further.

пример

main.py

from kivy.app import App
from kivy.config import Config
from MainPage import MainPage
from AboutPage import AboutPage
from MainContainer import MainContainer


class MyApp(App):

    def build(self):
        return MainContainer()


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

my.kv

#:kivy 1.10.1
#:import CardTransition kivy.uix.screenmanager.CardTransition
#:set menucolor1 0, 0.603, 0.784, 1
#:set menucolor2 0, 0.203, 0.384, 1
#:set backgroundcolor 0.95, 0.95, 0.95, 1

<MenuButton@Button>:
    size_hint_y: None
    height: 50
    markup: True

<MenuSpacer@Label>:
    size_hint_y: None
    height: 3
    canvas.before:
        Color:
            rgba: menucolor1
        Rectangle:
            pos: self.pos
            size: self.size
<MainPage>:
    canvas.before:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    name: 'main_screen'
    Label:
        color: menucolor1
        text: "Hi I'm Main Screen"

<AboutPage>:
    canvas:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    name: 'about_screen'
    Label:
        color: menucolor1
        text: "Hi I'm About Screen"


<MainContainer>:
    manager: manager
    canvas:
        Color:
            rgba: backgroundcolor
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        size: root.size
        orientation: 'horizontal'
        BoxLayout:
            orientation: 'vertical'
            width: 150
            size_hint_x: None
            MenuButton:
                text: '[b]Main[/b]'
                on_press: root.switch_to('main_screen')
            MenuSpacer:
            MenuButton:
                text: "[b]About[/b]"
                on_press: root.switch_to('about_screen')
            MenuSpacer:
            MenuButton:
                text: "[b]DummyConnect[/b]"
                on_press:
                    root.on_session()
            Widget:
                canvas.before:
                    Color:
                        rgba: menucolor1
                    Rectangle:
                        pos: self.pos
                        size: self.size
        ScreenManager:
            id: manager
            transition: CardTransition(direction='right',mode='push',duration=0.2)

            MainPage:
                id: main_page

            AboutPage:
                id: about_page

MainContainer.py

from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty


class MainContainer(Widget):

    manager = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(MainContainer, self).__init__(**kwargs)
        self.register_event_type('on_connect')
        print(self.children)
        self.bind(on_connect=self.ids.main_page.on_connect)
        self.bind(on_connect=self.ids.about_page.on_connect)

    def switch_to(self, name):
        self.manager.current = name

    def on_connect(self, *args):
        print("\nMainContainer.on_connect()")
        print("hello there")
        # return True   # indicating that we have consumed the touch and don’t want it to propagate any further.

    def on_session(self):
        print("session connected!")
        self.dispatch('on_connect')

MainPage.py

from kivy.uix.screenmanager import Screen


class MainPage(Screen):

    def on_connect(self, *args):
        print("\nMainPage.on_connect()")
        # return True   # indicating that we have consumed the touch and don’t want it to propagate any further.

AboutPage

from kivy.uix.screenmanager import Screen


class AboutPage(Screen):

    def on_connect(self, *args):
        print("\nAboutPage.on_connect()")
        # return True   # indicating that we have consumed the touch and don’t want it to propagate any further.

Выход

Img01

Другие вопросы по тегам