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]

Kivy Scrollview:AttributeError:“NoneType”对象没有属性“绑定”

Kivy Buildozer AttributeError:“上下文”对象没有属性“hostpython”