python - KivyMD:AttributeError:“NoneType”对象在添加 MDToolbar 时没有属性“theme_cls”
问题描述
我正在使用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()
解决方案
All code here works with Kivy 1.11.1 and KivyMD 0.102.0. KivyMD is in alpha status and API can be changed in future.
- Create all widgets inside build function. You should move creating of ScreenManager:
def build(self):
sm = ScreenManager()
sm.add_widget(inventory(name='inventory'))
return sm
- NavigationLayout cannot take more than two widgets, one of them is MDNavigationDrawer and second is layout. Create BoxLayout and put in it MDToolbar and Button:
NavigationLayout:
MDNavigationDrawer:
# ...
NavigationDrawerSubheader:
# ...
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "test"
Button:
text: "test"
on_release: app.nav_drawer.toggle()
- Id property in kv code should be without "":
NavigationLayout:
id: nav_layout
MDNavigationDrawer:
id: nav_drawer
To call widget by id you should use
app.root.ids.nav_drawer
.To toggle NavigationDrawer you should call NavigationLayout:
app.root.ids.nav_layout.toggle_nav_drawer()
.Usually NavigationLayout used as root widget. Add ScreenManager to BoxLayout.
You can add screens to ScreenManager using kv code:
ScreenManager:
id: screen_manager
Inventory:
name: "inventory"
- Do not combine layouts. Do not write
class Inventory(BoxLayout, Screen):
. Create BoxLayout inside your screen:
<Inventory>:
BoxLayout:
orientation: "vertical"
Final code will be:
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()
推荐阅读
- java - 如何将只读属性应用于 C: 目录中的所有 .docx 和 .pptx 文件?使用 java
- php - 如何排列以下数组?
- c# - 从单词列表中将多个单词替换为字符串中的其他单词
- sql - 插入中的VBA SQL错误
- postgresql - Postgresql - 不区分大小写的构建,允许所有 where、连接、分组等不区分大小写
- c# - 更改配置文件中的值c#
- ruby - 在 Ruby 中创建动态函数
- python - Pandas 处理精度为 00 的行为
- javascript - 当我点击它时,ng-href 除了更新链接或地址栏外没有响应(Angular Js)
- vba - VBA Application.run“此工作簿”属性语法