为什么kivy root.manager return None?
Why does kivy root.manager return None?
我目前正在构建一个用于自我测量的应用程序。我遇到了以下问题:我想要一个结果屏幕,其中包含我的成就进度条。到目前为止它看起来像这样:
<ResultScreen>:
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
max : 1000
value : root.manager.get_screen('music').slider.value
问题是,root.manager
应用于给定屏幕的 Button
和 returns 时工作正常。但是在 ProgressBar
中似乎是 None
和 returns 出现以下错误:
AttributeError: 'NoneType' object has no attribute 'get_screen'
怎么了?
完整代码:
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import (
NumericProperty, ReferenceListProperty, ObjectProperty
)
from kivy.vector import Vector
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen
class PongScreen(Screen):
pass
class MusicScreen(Screen):
pass
class DiscreteScreen(Screen):
pass
class ResultScreen(Screen):
pass
class PongApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(PongScreen(name='menu'))
sm.add_widget(MusicScreen(name='music'))
sm.add_widget(DiscreteScreen(name='discrete'))
sm.add_widget(ResultScreen(name='result'))
return sm
if __name__ == '__main__':
PongApp().run()
pong.kv:
#:kivy 1.0.9
#:import Factory kivy.factory.Factory
<MusicScreen>:
BoxLayout:
Button:
text: 'Назад в меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Дальше, к дискретке'
on_press: root.manager.current = 'discrete'
Slider:
id: slider
min: 0
max: 20
step: 1
orientation: 'vertical'
Label:
text: 'Тактов выучено\n' + str(slider.value)
CheckBox:
id : new_song_checkbox
Label:
text : 'Новую песню выучил?\n' + str(new_song_checkbox.active)
CheckBox:
id : music_pleasure_checkbox
Label:
text : 'Доволен ли исполнением\n' + str(music_pleasure_checkbox.active)
<DiscreteScreen>:
BoxLayout:
Button:
text: 'В меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
Slider:
id: slider
min: 0
max: 180
step: 15
orientation: 'vertical'
Label:
text: 'Минут на код затрачено\n' + str(slider.value)
CheckBox:
id : article_checkbox
Label:
text : 'Статью прочитал?\n' + str(article_checkbox.active)
CheckBox:
id : lecture_checkbox
Label:
text : 'Посмотрел ли лекцию?\n' + str(lecture_checkbox.active)
<DiscreteScreen>:
BoxLayout:
Button:
text: 'В меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
Button:
text: 'Дальше, к результатам'
on_press: root.manager.current = 'result'
Slider:
id: slider
min: 0
max: 180
step: 15
orientation: 'vertical'
Label:
text: 'Минут на код затрачено\n' + str(slider.value)
CheckBox:
id : article_checkbox
Label:
text : 'Статью прочитал?\n' + str(article_checkbox.active)
CheckBox:
id : lecture_checkbox
Label:
text : 'Посмотрел ли лекцию?\n' + str(lecture_checkbox.active)
<ResultScreen>:
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
max : 1000
value : root.manager.get_screen('music').slider.value
<PongScreen>:
BoxLayout:
Button:
text: 'К музыке'
on_press: root.manager.current = 'music'
Button:
text: 'К дискретке'
on_press: root.manager.current = 'discrete'
Button:
text: 'К результатам'
on_press: root.manager.current = 'result'
Button:
text: 'Выход'
on_press: app.stop()
首先,value : root.manager.get_screen('music').slider.value
是错误的,因为 root.manager.get_screen('music')
应该是一个 Screen
对象,默认情况下它没有(也不在您的代码中)任何道具。 slide
.
也许你的意思是 value : root.manager.get_screen('music').ids.slider.value
。但这不会解决你的问题。让我们尝试用简单的方式来分析问题。
调用方法 run
时,首先应用 kv-rules(通过方法 load_kv
),然后调用方法 build
。在方法 build
中,您首先定义了 ScreenManager
,然后添加了 Screens
并在 kvlang
中描述了屏幕。现在,当它遇到您的 .kv
文件并查找 root.manager
(在 value : root.manager.get_screen('music').ids.slider.value
中)时,它会找到 None
(默认值,因为它尚未添加到 ScreenManager
,在您的 build
方法中定义)。这就是 AttributeError
.
背后的原因
现在解决这个问题的方法有很多,
- 您通过
on_enter
等(built-in 或自定义)方法延迟了值分配过程,因为,
<ResultScreen>:
on_enter: pb.value = self.manager.get_screen('music').ids.slider.value
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
id: pb
max : 1000
- 将条件语句(可能更可取)设置为,
ProgressBar:
id: pb
max : 1000
value : root.manager.get_screen('music').ids.slider.value if root.manager is not None else 0
- 完全在
kvlang
. 中定义root
(即这里的ScreenManager
)
其他方法可能是在关联 class 中为 slide.value
创建一个 属性;在 build
方法等中管理它
我目前正在构建一个用于自我测量的应用程序。我遇到了以下问题:我想要一个结果屏幕,其中包含我的成就进度条。到目前为止它看起来像这样:
<ResultScreen>:
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
max : 1000
value : root.manager.get_screen('music').slider.value
问题是,root.manager
应用于给定屏幕的 Button
和 returns 时工作正常。但是在 ProgressBar
中似乎是 None
和 returns 出现以下错误:
AttributeError: 'NoneType' object has no attribute 'get_screen'
怎么了?
完整代码:
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import (
NumericProperty, ReferenceListProperty, ObjectProperty
)
from kivy.vector import Vector
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen
class PongScreen(Screen):
pass
class MusicScreen(Screen):
pass
class DiscreteScreen(Screen):
pass
class ResultScreen(Screen):
pass
class PongApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(PongScreen(name='menu'))
sm.add_widget(MusicScreen(name='music'))
sm.add_widget(DiscreteScreen(name='discrete'))
sm.add_widget(ResultScreen(name='result'))
return sm
if __name__ == '__main__':
PongApp().run()
pong.kv:
#:kivy 1.0.9
#:import Factory kivy.factory.Factory
<MusicScreen>:
BoxLayout:
Button:
text: 'Назад в меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Дальше, к дискретке'
on_press: root.manager.current = 'discrete'
Slider:
id: slider
min: 0
max: 20
step: 1
orientation: 'vertical'
Label:
text: 'Тактов выучено\n' + str(slider.value)
CheckBox:
id : new_song_checkbox
Label:
text : 'Новую песню выучил?\n' + str(new_song_checkbox.active)
CheckBox:
id : music_pleasure_checkbox
Label:
text : 'Доволен ли исполнением\n' + str(music_pleasure_checkbox.active)
<DiscreteScreen>:
BoxLayout:
Button:
text: 'В меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
Slider:
id: slider
min: 0
max: 180
step: 15
orientation: 'vertical'
Label:
text: 'Минут на код затрачено\n' + str(slider.value)
CheckBox:
id : article_checkbox
Label:
text : 'Статью прочитал?\n' + str(article_checkbox.active)
CheckBox:
id : lecture_checkbox
Label:
text : 'Посмотрел ли лекцию?\n' + str(lecture_checkbox.active)
<DiscreteScreen>:
BoxLayout:
Button:
text: 'В меню'
on_press: root.manager.current = 'menu'
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
Button:
text: 'Дальше, к результатам'
on_press: root.manager.current = 'result'
Slider:
id: slider
min: 0
max: 180
step: 15
orientation: 'vertical'
Label:
text: 'Минут на код затрачено\n' + str(slider.value)
CheckBox:
id : article_checkbox
Label:
text : 'Статью прочитал?\n' + str(article_checkbox.active)
CheckBox:
id : lecture_checkbox
Label:
text : 'Посмотрел ли лекцию?\n' + str(lecture_checkbox.active)
<ResultScreen>:
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
max : 1000
value : root.manager.get_screen('music').slider.value
<PongScreen>:
BoxLayout:
Button:
text: 'К музыке'
on_press: root.manager.current = 'music'
Button:
text: 'К дискретке'
on_press: root.manager.current = 'discrete'
Button:
text: 'К результатам'
on_press: root.manager.current = 'result'
Button:
text: 'Выход'
on_press: app.stop()
首先,value : root.manager.get_screen('music').slider.value
是错误的,因为 root.manager.get_screen('music')
应该是一个 Screen
对象,默认情况下它没有(也不在您的代码中)任何道具。 slide
.
也许你的意思是 value : root.manager.get_screen('music').ids.slider.value
。但这不会解决你的问题。让我们尝试用简单的方式来分析问题。
调用方法 run
时,首先应用 kv-rules(通过方法 load_kv
),然后调用方法 build
。在方法 build
中,您首先定义了 ScreenManager
,然后添加了 Screens
并在 kvlang
中描述了屏幕。现在,当它遇到您的 .kv
文件并查找 root.manager
(在 value : root.manager.get_screen('music').ids.slider.value
中)时,它会找到 None
(默认值,因为它尚未添加到 ScreenManager
,在您的 build
方法中定义)。这就是 AttributeError
.
现在解决这个问题的方法有很多,
- 您通过
on_enter
等(built-in 或自定义)方法延迟了值分配过程,因为,
<ResultScreen>:
on_enter: pb.value = self.manager.get_screen('music').ids.slider.value
BoxLayout:
Button:
text: 'Назад, к музыке'
on_press: root.manager.current = 'music'
ProgressBar:
id: pb
max : 1000
- 将条件语句(可能更可取)设置为,
ProgressBar:
id: pb
max : 1000
value : root.manager.get_screen('music').ids.slider.value if root.manager is not None else 0
- 完全在
kvlang
. 中定义
root
(即这里的ScreenManager
)
其他方法可能是在关联 class 中为 slide.value
创建一个 属性;在 build
方法等中管理它