Kivy - AttributeError:“NoneType”对象没有属性“add_widget”
Posted
技术标签:
【中文标题】Kivy - AttributeError:“NoneType”对象没有属性“add_widget”【英文标题】:Kivy - AttributeError: 'NoneType' object has no attribute 'add_widget' 【发布时间】:2021-10-16 20:27:21 【问题描述】:我一直在尝试使用 Kivy 编写一个简单的 python 应用程序,但是因为我更专注于后端而不是前端,所以我遇到了很多困难。提前我想警告一下,我将在这篇文章中粘贴大量代码,但请不要气馁,因为它可能是最基本的 kivy 代码。我的项目结构如下:
main.py 看起来像这样并启动整个应用程序:
import source.app.application
def main():
source.app.application.Main().run()
if __name__ == '__main__':
main()
application.py 负责应用程序的总体外观:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import ObjectProperty
from .main_screen.main_screen import MainScreen
from .search_screen.search_screen import SearchScreen
from .view_screen.view_screen import ViewScreen
Builder.load_file('source/app/application.kv')
class MultiScreen(ScreenManager):
pass
class HomeButton(BoxLayout):
pass
class SearchButton(BoxLayout):
pass
class ViewButton(BoxLayout):
pass
class Area(BoxLayout):
multi_screen = ObjectProperty(None)
def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)
def change_to_home(self):
self.multi_screen.transition.direction = 'right'
self.multi_screen.current = 'main'
def change_to_search(self):
if self.multi_screen.current == 'main':
self.multi_screen.transition.direction = 'left'
else: self.multi_screen.transition.direction = 'right'
self.multi_screen.current = 'search'
def change_to_view(self):
self.multi_screen.transition.direction = 'left'
self.multi_screen.current = 'view'
class Main(App):
def build(self):
return Area()
这里是application.kv:
#:kivy 2.0.0
<Area>:
orientation: 'vertical'
multi_screen: multi_screen
MultiScreen:
id: multi_screen
size_hint: 1, 895
MainScreen:
name: 'main'
SearchScreen:
name: 'search'
ViewScreen:
name: 'view'
Widget:
size_hint: 1, 5
canvas:
Color:
rgba: 0, 0, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint: 1, 100
spacing: 0
HomeButton:
Button:
text: 'Home'
on_release: root.change_to_home()
SearchButton:
Button:
text: 'Search'
on_release: root.change_to_search()
ViewButton:
Button:
text: 'View'
on_release: root.change_to_view()
现在问题出在 main_screen.py 上。它实现了 MainScreen 类,该类旨在用作 application.py 中屏幕管理器中的屏幕。它看起来像这样:
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.clock import Clock
from source.database.database_communicator import DatabaseCommunicator
from source.database.database_entry import Entry
Builder.load_file('source/app/main_screen/main_screen.kv')
class MainScreen(Screen):
scroll_box_layout = ObjectProperty(None)
def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)
#self._communicator = DatabaseCommunicator('database')
#self.discovered, self.undiscovered = self._communicator.get_list_of_words()
self.total_viewed = 0
self._build_box_layout()
def _choose_entry(self):
x = Entry('hello', 10)
return x
def _build_box_layout(self):
entry = self._choose_entry()
for i in range(100):
self.scroll_box_layout.add_widget(Button(text=str(i), size_hint_y=None, height=40))
_choose_entry 和 _build_box_layout 将来会有不同的 body,但现在它们只是用按钮填充滚动视图。最后是 main_screen.kv:
#:kivy 2.0.0
<MainScreen>:
scroll_box_layout: scroll_box_layout
ScrollView:
BoxLayout:
id: scroll_box_layout
orientation: 'vertical'
当我运行 main.py 时出现以下错误:
AttributeError: 'NoneType' 对象没有属性 'add_widget'
我在 *** 中检查了类似的问题并尝试了以下解决方案:
在application.py中直接导入main_screen.kv 直接在application.kv中导入main_screen.kv 在 MainScreen 构造函数中使用 schedule_once 将 scroll_box_layout 定义移动到不同的地方这些都不起作用。当 ObjectProperty 将 .py 文件中的对象链接到 .kv 文件中的对象时,它必须是某些东西。不幸的是,我对 kivy 的经验太少,无法找到导致此问题的原因。如果你能帮助我,我会很高兴。
编辑。这是完整的回溯
Traceback (most recent call last):
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/main.py", line 7, in <module>
main()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/main.py", line 4, in main
source.app.application.Main().run()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/app.py", line 949, in run
self._run_prepare()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/app.py", line 919, in _run_prepare
root = self.build()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/source/app/application.py", line 50, in build
return Area()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/source/app/application.py", line 30, in __init__
super().__init__(*args, **kargs)
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/uix/boxlayout.py", line 145, in __init__
super(BoxLayout, self).__init__(**kwargs)
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/uix/layout.py", line 76, in __init__
super(Layout, self).__init__(**kwargs)
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/uix/widget.py", line 359, in __init__
self.apply_class_lang_rules(
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/uix/widget.py", line 463, in apply_class_lang_rules
Builder.apply(
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/lang/builder.py", line 541, in apply
self._apply_rule(
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/lang/builder.py", line 663, in _apply_rule
self._apply_rule(
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/vocab/lib/python3.9/site-packages/kivy/lang/builder.py", line 659, in _apply_rule
child = cls(__no_builder=True)
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/source/app/main_screen/main_screen.py", line 21, in __init__
self._build_box_layout()
File "/home/whistleroosh/Desktop/minimalistic_english_vocabulary_app/source/app/main_screen/main_screen.py", line 31, in _build_box_layout
self.scroll_box_layout.add_widget(Button(text=str(i), size_hint_y=None, height=40))
AttributeError: 'NoneType' object has no attribute 'add_widget'
【问题讨论】:
请添加完整的回溯,包括行号。 @blackbrandt 添加 :) 【参考方案1】:我认为您只是太早调用self._build_box_layout()
(在设置scroll_box_layout
属性之前)。尝试替换:
self._build_box_layout()
与:
Clock.schedule_once(lambda dt: self._build_box_layout())
【讨论】:
非常感谢。我之前尝试使用 schedule_once,但似乎我用错了方法,所以谢谢你的澄清 对此有什么解释吗?我有一个类似的问题,如果我只是以 root 身份插入一个额外的小部件(而不是直接在构建中声明轮播),我会收到此错误。 我的猜测是 Kivy 在调用 init 之后而不是在调用之前初始化 ObjectProperty以上是关于Kivy - AttributeError:“NoneType”对象没有属性“add_widget”的主要内容,如果未能解决你的问题,请参考以下文章
新的 Kivy 安装:AttributeError: 'module' 对象没有属性 'require'
AttributeError:“kivy.properties.ObjectProperty”对象没有属性“manager1”
Kivy - AttributeError:“NoneType”对象没有属性“add_widget”
AttributeError:“超级”对象没有属性“__getattr__”[疑难解答:Kivy]