Python KivyMD:如何使 toggle_nav_drawer() 函数起作用?
Python KivyMD: How can I make the toggle_nav_drawer() function work?
我的 kv 代码有问题。我想用一些 NavigationDrawerIconButtons
创建一个 MDNavigationDrawer
。 window 出现,但当我单击 MDToolbar 时,程序崩溃并显示此错误消息。
Traceback (most recent call last):
File "C:/Users/path/to/my/file/main.py", line 189, in <module>
KivyGUI().run()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\app.py", line 855, in run
runTouchApp()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\core\window\window_sdl2.py", line 746, in mainloop
self._mainloop()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\core\window\window_sdl2.py", line 478, in _mainloop
EventLoop.idle()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 342, in idle
self.dispatch_input()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 327, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 293, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "C:\Users\uname\Anaconda3\lib\site-packages\kivymd\ripplebehavior.py", line 84, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\uname\Anaconda3\lib\site-packages\kivymd\button.py", line 480, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
File "C:\Users\path\to\my\file\design.kv", line 59, in <lambda>
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'LayoutPy' object has no attribute 'toggle_nav_drawer'
我从一个单独的文件导入 kv 代码。
#:kivy 1.11.0
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
#:import NavigationDrawerSubheader kivymd.navigationdrawer.NavigationDrawerSubheader
#:import MDToolbar kivymd.toolbar.MDToolbar
<ContentNavigationDrawer@MDNavigationDrawer>:
drawer_logo: 'src/LinguIcon.png'
NavigationDrawerSubheader:
text: "Menu:"
<LayoutPy>:
orientation: 'vertical'
scr_mngr: scr_mngr
NavigationLayout:
id: nav_layout
ContentNavigationDrawer:
id: nav_drawer
name: 'nav_drawer'
NavigationDrawerToolbar:
title: 'Options'
NavigationDrawerIconButton:
icon: 'settings'
text: 'Select Language'
on_release: root.open2ndScreen('screen_card')
NavigationDrawerIconButton:
icon: 'close'
text: 'Exit'
on_release: root.exit()
NavigationDrawerIconButton:
icon: 'face'
text: 'Contact the developer'
on_release: root.sendDevHint()
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar
title: 'Menu'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
Widget:
ScreenManager:
id: scr_mngr
screen_main: screen_main
Screen:
id: screen_main
name: 'screen_main'
input_words: input_words
lbl: lbl
btn: btn
FloatLayout:
### A few widgets ###
Screen:
id: screen_card
name: 'screen_card'
FloatLayout:
### A few widgets ###
Python代码:
import sys
import kivy
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivymd.theming import ThemeManager
from kivymd.label import MDLabel
from kivymd.textfields import MDTextField, MDTextFieldClear, MDTextFieldRect, MDTextFieldRound
from kivy.lang import Builder
from kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerIconButton, NavigationLayout
from kivy.properties import ObjectProperty
from kivymd.toast import toast
kivy.require('1.11.0')
class LayoutPy(FloatLayout):
def __init__(self, **kwargs):
super(LayoutPy, self).__init__(**kwargs)
self.scr_mngr = ObjectProperty(None)
self.build_nav_btns()
def callback(self, instance, value):
toast("Pressed item menu %d" % value)
def exit(self):
sys.exit(1)
def build_nav_btns(self):
btns = ["Select Language", "Contact the developer", "Exit"]
for count, btn in enumerate(btns):
if count == 1:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='settings', text=btn,
on_release=lambda x, btn: self.callback(x, btn)))
elif count == 2:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='face', text=btn,
on_release=lambda x, btn: self.callback(x, btn)))
elif count == 3:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='close', text=btn,
on_release=lambda x: self.exit()))
Builder.load_file("design.kv")
class KivyGUI(App):
theme_cls = ThemeManager()
theme_cls.primary_palette = ("Teal")
title = ("App")
def build(self):
c = LayoutPy()
return c
if __name__ == "__main__":
KivyGUI().run()
我 删减了很多 的 Python 代码,所以对您来说更清晰一些。我不认为这是模块本身的问题,因为 KivyMD example code works fine for me (Thats also what the solution should look like when I run it). I think the problem is that my LayoutPy
class inherits from FloatLayout
which has no toggle_nav_drawer
object... but I have no idea now how I could implement a suitable solution into my existing code (I am trying for 2 days now). If you need the whole code (everything almost worked fine before adding the NavigationDrawer
) you can take a look here.
非常感谢!
错误 - 属性错误
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'LayoutPy' object has no attribute 'toggle_nav_drawer'
根本原因
对象 LayoutPy
没有属性 toggle_nav_drawer
因为 toggle_nav_drawer
是在 LayoutPy
的实例化子对象 NavigationLayout:
中定义的。
解决方案
将root.toggle_nav_drawer()
替换为root.ids.nav_layout.toggle_nav_drawer()
片段 - kv 文件
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar
title: 'Menu'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['dots-vertical', lambda x: root.ids.nav_layout.toggle_nav_drawer()]]
输出
我的 kv 代码有问题。我想用一些 NavigationDrawerIconButtons
创建一个 MDNavigationDrawer
。 window 出现,但当我单击 MDToolbar 时,程序崩溃并显示此错误消息。
Traceback (most recent call last):
File "C:/Users/path/to/my/file/main.py", line 189, in <module>
KivyGUI().run()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\app.py", line 855, in run
runTouchApp()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\core\window\window_sdl2.py", line 746, in mainloop
self._mainloop()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\core\window\window_sdl2.py", line 478, in _mainloop
EventLoop.idle()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 342, in idle
self.dispatch_input()
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 327, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\base.py", line 293, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "C:\Users\uname\Anaconda3\lib\site-packages\kivymd\ripplebehavior.py", line 84, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\uname\Anaconda3\lib\site-packages\kivymd\button.py", line 480, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\uname\Anaconda3\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
File "C:\Users\path\to\my\file\design.kv", line 59, in <lambda>
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'LayoutPy' object has no attribute 'toggle_nav_drawer'
我从一个单独的文件导入 kv 代码。
#:kivy 1.11.0
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
#:import NavigationDrawerSubheader kivymd.navigationdrawer.NavigationDrawerSubheader
#:import MDToolbar kivymd.toolbar.MDToolbar
<ContentNavigationDrawer@MDNavigationDrawer>:
drawer_logo: 'src/LinguIcon.png'
NavigationDrawerSubheader:
text: "Menu:"
<LayoutPy>:
orientation: 'vertical'
scr_mngr: scr_mngr
NavigationLayout:
id: nav_layout
ContentNavigationDrawer:
id: nav_drawer
name: 'nav_drawer'
NavigationDrawerToolbar:
title: 'Options'
NavigationDrawerIconButton:
icon: 'settings'
text: 'Select Language'
on_release: root.open2ndScreen('screen_card')
NavigationDrawerIconButton:
icon: 'close'
text: 'Exit'
on_release: root.exit()
NavigationDrawerIconButton:
icon: 'face'
text: 'Contact the developer'
on_release: root.sendDevHint()
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar
title: 'Menu'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
Widget:
ScreenManager:
id: scr_mngr
screen_main: screen_main
Screen:
id: screen_main
name: 'screen_main'
input_words: input_words
lbl: lbl
btn: btn
FloatLayout:
### A few widgets ###
Screen:
id: screen_card
name: 'screen_card'
FloatLayout:
### A few widgets ###
Python代码:
import sys
import kivy
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivymd.theming import ThemeManager
from kivymd.label import MDLabel
from kivymd.textfields import MDTextField, MDTextFieldClear, MDTextFieldRect, MDTextFieldRound
from kivy.lang import Builder
from kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerIconButton, NavigationLayout
from kivy.properties import ObjectProperty
from kivymd.toast import toast
kivy.require('1.11.0')
class LayoutPy(FloatLayout):
def __init__(self, **kwargs):
super(LayoutPy, self).__init__(**kwargs)
self.scr_mngr = ObjectProperty(None)
self.build_nav_btns()
def callback(self, instance, value):
toast("Pressed item menu %d" % value)
def exit(self):
sys.exit(1)
def build_nav_btns(self):
btns = ["Select Language", "Contact the developer", "Exit"]
for count, btn in enumerate(btns):
if count == 1:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='settings', text=btn,
on_release=lambda x, btn: self.callback(x, btn)))
elif count == 2:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='face', text=btn,
on_release=lambda x, btn: self.callback(x, btn)))
elif count == 3:
self.ids.nav_drawer.add_widget(
NavigationDrawerIconButton(
icon='close', text=btn,
on_release=lambda x: self.exit()))
Builder.load_file("design.kv")
class KivyGUI(App):
theme_cls = ThemeManager()
theme_cls.primary_palette = ("Teal")
title = ("App")
def build(self):
c = LayoutPy()
return c
if __name__ == "__main__":
KivyGUI().run()
我 删减了很多 的 Python 代码,所以对您来说更清晰一些。我不认为这是模块本身的问题,因为 KivyMD example code works fine for me (Thats also what the solution should look like when I run it). I think the problem is that my LayoutPy
class inherits from FloatLayout
which has no toggle_nav_drawer
object... but I have no idea now how I could implement a suitable solution into my existing code (I am trying for 2 days now). If you need the whole code (everything almost worked fine before adding the NavigationDrawer
) you can take a look here.
非常感谢!
错误 - 属性错误
left_action_items: [['dots-vertical', lambda x: root.toggle_nav_drawer()]]
File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
AttributeError: 'LayoutPy' object has no attribute 'toggle_nav_drawer'
根本原因
对象 LayoutPy
没有属性 toggle_nav_drawer
因为 toggle_nav_drawer
是在 LayoutPy
的实例化子对象 NavigationLayout:
中定义的。
解决方案
将root.toggle_nav_drawer()
替换为root.ids.nav_layout.toggle_nav_drawer()
片段 - kv 文件
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: toolbar
title: 'Menu'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['dots-vertical', lambda x: root.ids.nav_layout.toggle_nav_drawer()]]