KivyMD:AttributeError:添加MDToolbar时,“ NoneType”对象没有属性“ theme_cls”

时间:2019-11-13 22:42:19

标签: python kivy kivy-language

我正在使用 Kivy KivyMD ,我正在尝试实现 MDToolbar 。运行程序后,出现以下错误:AttributeError: 'NoneType' object has no attribute 'theme_cls'。我只包含程序中的相关代码。一切正常,直到添加 MDToolbar 为止。如何使 MDToolbar 工作?请帮忙!

我的完整错误:

Parser: File "<inline>", line 22:
...
     20:<MDToolbar>
     21:    size_hint_y: None
>>   22:    height: root.theme_cls.standard_increment
     23:    padding: [root.theme_cls.horizontal_margins - dp(12), 0]
     24:    opposite_colors: True
...
AttributeError: 'NoneType' object has no attribute 'theme_cls'
  File "C:\Users\kelleym\AppData\Local\Continuum\anaconda3\lib\site-packages\kivy\lang\builder.py", line 696, in _apply_rule
    setattr(widget_set, key, value)
  File "kivy\weakproxy.pyx", line 35, in kivy.weakproxy.WeakProxy.__setattr__
  File "kivy\properties.pyx", line 497, in kivy.properties.Property.__set__
  File "kivy\properties.pyx", line 544, in kivy.properties.Property.set
  File "kivy\properties.pyx", line 599, in kivy.properties.Property.dispatch
  File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
  File "kivy\_event.pyx", line 1120, in kivy._event.EventObservers._dispatch
  File "kivy\properties.pyx", line 1318, in kivy.properties.ReferenceListProperty.trigger_change
  File "kivy\properties.pyx", line 1333, in kivy.properties.ReferenceListProperty.trigger_change
  File "kivy\properties.pyx", line 599, in kivy.properties.Property.dispatch
  File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
  File "kivy\_event.pyx", line 1120, in kivy._event.EventObservers._dispatch
  File "C:\Users\kelleym\AppData\Local\Continuum\anaconda3\lib\site-packages\kivymd\uix\behaviors\elevation.py", line 105, in _update_shadow
    self._shadow = App.get_running_app().theme_cls.quad_shadow
  File "C:\Users\kelleym\Desktop\Actual Inventory App\main.py", line 313, in <module>
    sm.add_widget(inventory(name='inventory'))

我的代码:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.theming import ThemeManager

Builder.load_string("""
<inventory>:
    NavigationLayout:
        id: "nav_layout"
        MDToolbar:
            title: "test"
        MDNavigationDrawer:
            drawer_logo: "test.png"
            id: "nav_drawer"
            NavigationDrawerSubheader:
                text: "[color=#black]Categories[/color]"
            NavigationDrawerIconButton:
                icon: 'printer'
                text: "Printers"
                on_release: root.manager.current = 'printers'
            NavigationDrawerIconButton:
                text: "PCs"
                icon: "laptop"
            NavigationDrawerIconButton:
                text: "Monitors"
                icon: "monitor"
            NavigationDrawerIconButton:
                text: "Tablets"
                icon: "tablet"
            NavigationDrawerIconButton:
                text: "Non-HP"
                icon: "close-circle-outline"
            NavigationDrawerIconButton:
                text: "Supplies"
                icon: "water"
            NavigationDrawerIconButton:
                text: "Misc."
                icon: "paperclip"
        Button:
            text: "test"
            on_release: app.nav_drawer.toggle()
""")


class inventory(BoxLayout, Screen):
    pass


sm = ScreenManager()
sm.add_widget(inventory(name='inventory'))


class TestApp(App):
    theme_cls = ThemeManager()

    def build(self):
        return sm


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

1 个答案:

答案 0 :(得分:1)

  

此处的所有代码均适用于 Kivy 1.11.1 KivyMD 0.102.0 。 KivyMD处于 alpha 状态,将来可以更改API。

  1. build 函数中创建所有小部件。您应该移动创建 ScreenManager
    def build(self):
        sm = ScreenManager()
        sm.add_widget(inventory(name='inventory'))
        return sm
  1. NavigationLayout 不能使用两个以上的小部件,其中一个是 MDNavigationDrawer ,第二个是layout。创建 BoxLayout 并将其放入 MDToolbar Button
    NavigationLayout:
        MDNavigationDrawer:
            # ...
            NavigationDrawerSubheader:
                # ...
        BoxLayout:
            orientation: "vertical"
            MDToolbar:
                title: "test"
            Button:
                text: "test"
                on_release: app.nav_drawer.toggle()
    kv代码中的
  1. Id属性应不含“”:
    NavigationLayout:
        id: nav_layout
        MDNavigationDrawer:
            id: nav_drawer
  1. 要通过ID调用小部件,您应该使用app.root.ids.nav_drawer

  2. 要切换 NavigationDrawer ,您应该调用 NavigationLayout app.root.ids.nav_layout.toggle_nav_drawer()

  3. 通常 NavigationLayout 用作根窗口小部件。将 ScreenManager 添加到 BoxLayout

  4. 您可以使用kv代码将屏幕添加到 ScreenManager

        ScreenManager:
            id: screen_manager

            Inventory:
                name: "inventory"
  1. 请勿合并布局。不要写class Inventory(BoxLayout, Screen):。在屏幕内创建 BoxLayout
<Inventory>:
    BoxLayout:
        orientation: "vertical"

最终代码为:

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen
from kivymd.theming import ThemeManager

root_kv = """
NavigationLayout:
    id: nav_layout

    MDNavigationDrawer:
        id: nav_drawer
        drawer_logo: "test.png"

        NavigationDrawerSubheader:
            text: "Categories"
        NavigationDrawerIconButton:
            text: "Printers"
            icon: "printer"
            on_release: app.screen_manager.current = "printers"
        NavigationDrawerIconButton:
            text: "PCs"
            icon: "laptop"
        NavigationDrawerIconButton:
            text: "Monitors"
            icon: "monitor"
        NavigationDrawerIconButton:
            text: "Tablets"
            icon: "tablet"
        NavigationDrawerIconButton:
            text: "Non-HP"
            icon: "close-circle-outline"
        NavigationDrawerIconButton:
            text: "Supplies"
            icon: "water"
        NavigationDrawerIconButton:
            text: "Misc."
            icon: "paperclip"

    BoxLayout:
        orientation: "vertical"

        ScreenManager:
            id: screen_manager

            Inventory:
                name: "inventory"


<Inventory>:
    BoxLayout:
        orientation: "vertical"

        MDToolbar:
            title: "test"

        Button:
            text: "test"
            on_release: app.root.toggle_nav_drawer()
"""


class Inventory(Screen):
    pass


class MainApp(App):
    theme_cls = ThemeManager()
    screen_manager = ObjectProperty()

    def build(self):
        self.root = Builder.load_string(root_kv)
        self.screen_manager = self.root.ids.screen_manager


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