我正在制作用于互联网连接设备的Python / Kivy GUI。由于该设备使用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
因此,基本上我希望MyApp中调度的on_connect事件传播到MainPage和AboutPages,目前只有MainContainer定义了on_connect,但即使这样也不会触发。
我想我可以通过将其自己传播给每个小部件的所有子代来做到这一点,但是我还需要对所有的boxlayouts,screenmanager和screen实施它吗?我认为有更好的方法可以做到这一点,但我还没有找到。
感谢您的帮助!
答案 0 :(得分:1)
要将on_connect传播到所有屏幕,即MainPage和AboutPage。有关详细信息,请参阅示例。
return True
,表示我们已经消耗了触摸,不希望其进一步传播。我已注释掉return True
以显示事件传播。尝试取消注释return True
以显示传播已停止。
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.