如何防止Kivy中的Root-Widget的多个实例

时间:2017-11-13 18:45:40

标签: python-3.x kivy

好的,我尝试在Kivy制作我的第一个应用程序,并且我的Root Widget的多个实例出现问题。

我需要在运行时向我的应用添加小部件。 (显示电子表格)

但是由于Root Widget的多个实例,我无法使用kivy id查找对象访问小部件。

https://kivy.org/docs/guide/lang.html

我制作了三个按钮以在控制台中显示问题 按钮-1 - , - 2和-3 -

请解释为什么有多个实例以及我如何阻止它,因此代码可以正常工作。

感谢您的帮助!

档案 - > Match.py​​

    #!python
    from __future__ import print_function
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.properties import ObjectProperty, StringProperty
    from kivy.uix.boxlayout import BoxLayout
    from kivy.app import App
    import gc

    class my_gc():
        def search_g(self):
            for obj in gc.get_objects():
                if isinstance(obj, Root):
                    try:
                        print(obj.ids)
                    except:
                        print('fail')

    #Root Widget
    class Root(BoxLayout):

        sm = ObjectProperty(None)
        sc0 = ObjectProperty(None)
        sc1 = ObjectProperty(None)
        sc2 = ObjectProperty(None)
        sc3 = ObjectProperty(None)

        mylbl0 = StringProperty('screen 0')
        mylbl1 = StringProperty('screen 1')
        mylbl2 = StringProperty('screen 2')
        mylbl3 = StringProperty('screen 3')

        def find_ids(self):
            print(self.ids)

    class Screen_Manager(ScreenManager):
        pass

    class Screen_0(Screen):
        pass

    class Screen_1(Screen):
        pass

    class Screen_2(Screen):
        pass

    class Screen_3(Screen):
        pass

    class Match(App):
        rootwidget = Root()
        sm = Screen_Manager()
        gc = my_gc()

        def build(self):
            pass

    Match().run()

档案 - > Match.kv

    #Root Widget (BoxLayout)
    Root:
        sm: sm
        sc1: sc0
        sc1: sc1
        sc1: sc2
        sc1: sc3
        BoxLayout:
            spacing: '20dp'
            orientation: 'vertical'
            Screen_Manager:
                id: sm
                Screen_0:
                    id: sc0
                    name: 'sc0'
                    manager: 'sm'
                    BoxLayout:
                        id: box_0-0
                        Label:
                            id: lbl_0
                            text: app.rootwidget.mylbl0
                        Label:
                            id: lbl_0-1
                            text: root.mylbl0
                Screen_1:
                    id: sc1
                    name: 'sc1'
                    manager: 'sm'
                    Label:
                        id: lbl1
                        text: root.mylbl1
                Screen_2:
                    id: sc2
                    name: 'sc2'
                    manager: 'sm'
                    Label:
                        id: lbl2
                        text: root.mylbl2
                Screen_3:
                    id: sc3
                    name: 'sc3'
                    manager: 'sm'
                    Label:
                        id: lbl3
                        text: root.mylbl3

            #Tab-Buttons
            BoxLayout:
                size_hint: 1 , None
                height: '60dp'
                orientation: 'horizontal'
                Button:
                    text: '-0-'
                    on_press: root.sm.current = sc0.name
                Button:
                    text: '-1-'
                    on_press: root.sm.current = sc1.name
                Button:
                    text: '-2-'
                    on_press: root.sm.current = sc2.name
                Button:
                    text: '-3-'
                    on_press: root.sm.current = sc3.name
                Button:
                    text: '<'
                    size_hint: None , 1
                    width: '60dp'
                    on_press: root.sm.current = root.sm.previous()
                Button:
                    text: '>'
                    size_hint: None , 1
                    width: '60dp'
                    on_press: root.sm.current = root.sm.next()
                Button:
                    text: '-b1-'
                    size_hint: None , 1
                    width: '60dp'
                    #on_press: root.search_g()              #<-- doesn't work
                    on_press: app.gc.search_g()             #<-- works
                Button:
                    text: '-b2-'
                    size_hint: None , 1
                    width: '60dp'
                    on_press: root.find_ids()               #<-- doesn't work
                    on_press: app.rootwidget.find_ids()     #<-- works
                Button:
                    text: '-b3-'
                    size_hint: None , 1
                    width: '60dp'
                    on_press: print(root.mylbl1)            #<-- works
                    on_press: print(app.rootwidget.mylbl1)  #<-- works

1 个答案:

答案 0 :(得分:0)

Mutilple Instance - Root Widget

根据您的代码,您没有根小部件的多个实例。您的根小部件是 Root: ,根据kv文件, match.kv

root.search_g()

它不起作用,因为您的root(BoxLayout)类没有 search_g() 方法。

root.find_ids - 工作

当我评论 app.rootwidget.find_ids 时,对 root.find_ids 的调用有效,即它打印了ids。关键字 root 仅在规则定义中可用,并表示规则的根小部件(规则的第一个实例)。解析kv文件后,kivy会收集所有标记为id的小部件,并将它们放在 self.ids 字典类型属性中。

app.rootwidget.find_ids

它工作但没有id,因为它引用了发起的对象类Root中的方法find_ids。 rootwidget 只是一个名称变量,它与 Root:

从附带的屏幕截图中,您会注意到root.find_ids和app.rootwidget.find_ids的对象位置不同。

动态添加小部件

要在应用运行时动态添加小部件,您必须执行以下操作。有关示例,请参阅Kivy/python : when i click row then it shows error IndexError: list index out of range

上的其他帖子

Python脚本 - match.py​​

  1. 添加导入语句如下:

    来自kivy.properties导入ObjectProperty

  2. 声明变量(例如容器)或ObjectProperty类型,例如在类Root

    类Root(BoxLayout):     container = ObjectProperty(无)

  3. 在添加

  4. 之前删除所有动态添加的小部件
  5. 动态添加小部件。

  6. kv文件 - match.kv

    1. 定义布局,例如您的kv文件中的BoxLayout或GridLayout。
    2. 为布局添加ID,例如kv文件中的容器。
    3. 将ObjectProperty连接到id

      根:     容器:容器 ...     #动态添加小部件的容器     BoxLayout的:         id:container

    4. 解决方案

      解决方案是声明一个ObjectProperty,rootwidget如下:

      class Match(App):
          rootwidget = ObjectProperty(None)
          title = "Solution App"
      
          gc = my_gc()
      
          def build(self):
              self.rootwidget = Root()
              return self.rootwidget
      

      match.py​​

      #!python
      from __future__ import print_function
      from kivy.uix.screenmanager import ScreenManager, Screen
      from kivy.properties import ObjectProperty, StringProperty
      from kivy.uix.boxlayout import BoxLayout
      from kivy.app import App
      import gc
      
      
      class my_gc():
          def search_g(self):
              print("my_gc.search_g called")
              for obj in gc.get_objects():
                  if isinstance(obj, Root):
                      try:
                          print("obj={0}, ids={1}".format(obj, obj.ids))
                          for key, value in obj.ids.items():
                              print("   key={0}, value={1}".format(key, value))
                      except:
                          print('fail')
      
      
      # Root Widget
      class Root(BoxLayout):
          sm = ObjectProperty(None)
          sc0 = ObjectProperty(None)
          sc1 = ObjectProperty(None)
          sc2 = ObjectProperty(None)
          sc3 = ObjectProperty(None)
      
          mylbl0 = StringProperty('screen 0')
          mylbl1 = StringProperty('screen 1')
          mylbl2 = StringProperty('screen 2')
          mylbl3 = StringProperty('screen 3')
      
          def find_ids(self):
              print("Root.find_ids called")
              print("self={0}, self.ids={1}".format(self, self.ids))
              for key, value in self.ids.items():
                  print("   key={0}, value={1}".format(key, value))
      
      
      class Screen_Manager(ScreenManager):
          pass
      
      
      class Screen_0(Screen):
          pass
      
      
      class Screen_1(Screen):
          pass
      
      
      class Screen_2(Screen):
          pass
      
      
      class Screen_3(Screen):
          pass
      
      
      class Match(App):
          rootwidget = ObjectProperty(None)
          title = "Solution App"
      
          gc = my_gc()
      
          def build(self):
              self.rootwidget = Root()
              return self.rootwidget
      
      
      if __name__ == "__main__":
          Match().run()
      

      match.kv

      #Root Widget (BoxLayout)
      <Root>:
          sm: sm
          sc1: sc0
          sc1: sc1
          sc1: sc2
          sc1: sc3
      
          BoxLayout:
              spacing: '20dp'
              orientation: 'vertical'
              Screen_Manager:
                  id: sm
                  Screen_0:
                      id: sc0
                      name: 'sc0'
                      manager: 'sm'
                      BoxLayout:
                          id: box_0-0
                          Label:
                              id: lbl_0
                              text: root.mylbl0
                          Label:
                              id: lbl_0-1
                              text: root.mylbl0
                  Screen_1:
                      id: sc1
                      name: 'sc1'
                      manager: 'sm'
                      Label:
                          id: lbl1
                          text: root.mylbl1
                  Screen_2:
                      id: sc2
                      name: 'sc2'
                      manager: 'sm'
                      Label:
                          id: lbl2
                          text: root.mylbl2
                  Screen_3:
                      id: sc3
                      name: 'sc3'
                      manager: 'sm'
                      Label:
                          id: lbl3
                          text: root.mylbl3
      
              #Tab-Buttons
              BoxLayout:
                  id: secondBoxLayout
                  size_hint: 1 , None
                  height: '60dp'
                  orientation: 'horizontal'
                  Button:
                      text: '-0-'
                      on_press: root.sm.current = sc0.name
                  Button:
                      text: '-1-'
                      on_press: root.sm.current = sc1.name
                  Button:
                      text: '-2-'
                      on_press: root.sm.current = sc2.name
                  Button:
                      text: '-3-'
                      on_press: root.sm.current = sc3.name
                  Button:
                      text: '<'
                      size_hint: None , 1
                      width: '60dp'
                      on_press: root.sm.current = root.sm.previous()
                  Button:
                      text: '>'
                      size_hint: None , 1
                      width: '60dp'
                      on_press: root.sm.current = root.sm.next()
                  Button:
                      text: '-b1-'
                      size_hint: None , 1
                      width: '60dp'
                      on_press:
                          print("\non_press: {}".format(self.text))
                          # root.search_g()              #<-- doesn't work
                          print("    app.gc_search_g()")
                          app.gc.search_g()             #<-- works
                  Button:
                      text: '-b2-'
                      size_hint: None , 1
                      width: '60dp'
                      on_press:
                          print("\non_press: {}".format(self.text))
                          print("    root.find_ids()")
                          root.find_ids()               #<-- works
                          print("\n    app.root.find_ids()")
                          app.rootwidget.find_ids()     #<-- works
                  Button:
                      text: '-b3-'
                      size_hint: None , 1
                      width: '60dp'
                      on_press:
                          print("\non_press: {}".format(self.text))
                          print(root.mylbl1)            #<-- works
                          print(app.rootwidget.mylbl1)  #<-- works
      

      输出

      Figure 1 - Original Figure 2 - Solution