Reputation: 482
I am making a Python/Kivy GUI for internet connected device. There is lot of a sync stuff going on, as the device uses WAMP pub/sub method for communication. The problem is that I don't know how to propagate the custom events, suchs as on_connect, on_disconnect etc from the kivy app to the appropriate kivy widget.
Here is what I have now, stripped to the bare minimum for better readability, also dummy connect button, attached to simulate connect event happening.
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
So basically I'd like the on_connect event that is dispatched in MyApp to propagate to the MainPage and AboutPages, currently only the MainContainer has on_connect defined, but even that does not fire.
I guess I could do it by propgating it myself to all the childrens at each widget, but I would need to implement this to all the boxlayouts,screenmanagers and screens as well? I'd think there is a better way to do it but I did not find one yet.
Any help is appreciated!
Upvotes: 1
Views: 2378
Reputation: 16031
To propagate the on_connect to all the screens i.e. MainPage, and AboutPage. Please refer to the example for details.
return True
, indicating that we have consumed the touch and don’t want it to propagate any further.I have commented off return True
to show the event propagation. Try uncomment return True
to show propagation stopped.
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.
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()
#: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
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')
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.
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.
Upvotes: 3