代码之家  ›  专栏  ›  技术社区  ›  Ou Tsei

Kivy自定义事件传播

  •  0
  • Ou Tsei  · 技术社区  · 6 年前

    我正在为联网设备制作一个python/kivy GUI。由于设备使用wamp pub/sub方法进行通信,有很多同步的事情正在进行中。问题是,我不知道如何将自定义事件传播到适当的Kivy小部件,比如在连接、断开连接等方面。

    下面是我现在所拥有的,为了更好的可读性,将其剥离到最低限度,同时还附加了模拟连接事件发生的虚拟连接按钮。

    我的应用程序.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()
    

    M.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:
    

    主容器.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")
    

    主页.py

    from kivy.uix.screenmanager import Screen
    
    class MainPage(Screen):
        pass
    

    关于page.py

    from kivy.uix.screenmanager import Screen
    
    class AboutPage(Screen):
        pass
    

    所以基本上我希望在myapp中调度的on-connect事件传播到mainpage和aboutpages,目前只有maincontainer定义了on-connect,但即使这样也不会触发。

    我想我可以通过在每个小部件上把它自己支撑给所有的孩子来实现,但是我也需要把它实现到所有的盒子布局、屏幕管理器和屏幕上?我想有更好的办法,但我还没有找到。

    感谢您的帮助!

    1 回复  |  直到 6 年前
        1
  •  1
  •   ikolim    6 年前

    解决方案

    要在“连接”上传播,请连接到所有屏幕,即“主页”和“关于页”。有关详细信息,请参阅示例。

    1. 为主页和AboutPage添加了ID
    2. 将回调绑定到它们。调度事件时,将使用与该特定事件相关的参数调用回调。
    3. return true ,表示我们已经使用了touch并且不想让它进一步传播。
    4. 删除了app(main.py)中的代码,并在maincontainer.py中添加了一些代码。
    5. < > >

      注意

      我已经对显示事件传播的 return true 尝试取消注释 return true to show propagation stopped.

      代码段

      集装箱

      def_uuu init_uuuu(self,**kwargs):
      super(主容器,自身)。初始化(*kwargs)
      self.register_event_type('on_connect')
      打印(self.children)
      self.bind(on_connect=self.ids.main_page.on_connect)
      self.bind(on_connect=self.ids.about_page.on_connect)
      …
      def on ou connect(self,*参数):
      print(“\n连接()”上的minContainer.on)
      打印(“你好”
      #返回“真”,表示我们已经消耗了触摸,不希望它进一步传播。
      

      示例

      主要.py

      从kivy.app导入app 从kivy.config导入配置 从主页导入主页 从aboutpage导入aboutpage 从主容器导入主容器 类myapp(app): 定义构建(自身): 返回主容器() 如果“名称”, myapp()。运行()

      我的.kv

      :kivy 1.10.1
      #:导入cardttransition kivy.uix.screenmanager.cardttransition
      #:设置菜单颜色1 0、0.603、0.784、1
      #:设置菜单颜色2 0、0.203、0.384、1
      #:设置背景颜色0.95、0.95、0.95、1
      
      <menubutton@按钮>:
      大小提示:无
      高度:50
      标记:真
      
      <menuspacer@label>:
      大小提示:无
      高度:3
      画布。之前:
      颜色:
      RGBA:菜单颜色1
      矩形:
      位置:self.pos
      大小:self.size
      <主页>:
      画布。之前:
      颜色:
      rgba:背景色
      矩形:
      位置:self.pos
      大小:self.size
      name:'主屏幕'
      标签:
      颜色:menucolor1
      文本:“嗨,我是主屏幕”
      
      <关于第>页:
      画布:
      颜色:
      rgba:背景色
      矩形:
      位置:self.pos
      大小:self.size
      name:'关于屏幕'
      标签:
      颜色:menucolor1
      文本:“嗨,我是关于屏幕的”
      
      
      <主容器>:
      经理:经理
      画布:
      颜色:
      rgba:背景色
      矩形:
      位置:self.pos
      大小:self.size
      方框布局:
      大小:根。大小
      方向:“水平”
      方框布局:
      方向:“垂直”
      宽度:150
      大小\u提示\u x:无
      菜单按钮:
      文本:“[B]main[/B]”
      在“按:根”上。切换到(“主屏幕”)。
      菜单窗格:
      菜单按钮:
      文本:“[B]关于[/B]”
      在“按:根”上。切换到(“关于”屏幕)
      菜单窗格:
      菜单按钮:
      文本:“[B]DummConnect[/B]”
      按下:
      根目录。在会话()上
      小装置:
      画布。之前:
      颜色:
      RGBA:菜单颜色1
      矩形:
      位置:self.pos
      大小:self.size
      屏幕管理器:
      ID:经理
      转换:cardTransition(direction='right',mode='push',duration=0.2)
      
      主页:
      ID:主页
      
      关于页面:
      ID:关于页面
      

      主容器.py

      从kivy.uix.widget导入widget 从kivy.properties导入ObjectProperty 类主容器(小部件): Manager=ObjectProperty(无) 定义初始化(self,**kwargs): super(主容器,自身)。初始化(*kwargs) self.register_event_type('on_connect') 打印(self.children) self.bind(on_connect=self.ids.main_page.on_connect) self.bind(on_connect=self.ids.about_page.on_connect) def切换到(self,name): self.manager.current=名称 def on ou connect(self,*参数): print(“\n连接()”上的minContainer.on) 打印(“你好” #返回“真”,表示我们已经消耗了触摸,不希望它进一步传播。 def on ou会话(self): 打印(“会话已连接!”) self.dispatch(“连接”时)

      主页.py

      从kivy.uix.screenmanager导入屏幕 类主页(屏幕): def on ou connect(self,*参数): print(“\nmainpage.on_Connect()”) #返回“真”,表示我们已经消耗了触摸,不希望它进一步传播。

      关于页面

      从kivy.uix.screenmanager导入屏幕 类AboutPage(屏幕): def on ou connect(self,*参数): print(“\nabOutpage.on_Connect()”) #返回“真”,表示我们已经消耗了触摸,不希望它进一步传播。

      输出

      细节。

      1. 为主页和AboutPage添加了ID
      2. 将回调绑定到它们。调度事件时,将使用与该特定事件相关的参数调用回调。
      3. return True表示我们已经消耗了触摸,不希望它进一步传播。
      4. 删除了app(main.py)中的代码,并在maincontainer.py中添加了一些代码。

      注释

      我已经发表了评论返回true以显示事件传播。尝试取消注释返回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.
      

      例子

      主.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()
      

      千伏

      #: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
      

      主容器.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')
      

      主页.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.
      

      关于页面

      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