Error: In _update_shadow self._shadow = App.get_running_app().theme_cls.quad_shadow

ぃ、小莉子 提交于 2020-01-16 10:34:08

问题


I'm working in Kivy and KivyMD to build a GUI for a login function. My GUI works fine with Kivy code, but the second I change a Button to an MDRaisedButton, I get these two errors (full error code further below):

  1. AttributeError: 'NoneType' object has no attribute 'theme_cls'
  2. line 118, in _update_shadow self._shadow = App.get_running_app().theme_cls.quad_shadow

I'm curious to know if anyone else can pinpoint the problem, and explain it to me. Thank you!

I spent the past 8 hours rebuilding the entire application from a blank page to a new one, running the code between edits to see if I could pinpoint where it was breaking. Unfortunately, I couldn't figure out a solution to the problem.

framedesign.py

class LoginWindow(Screen):
    email = ObjectProperty(None)
    password = ObjectProperty(None)

    def loginBtn(self):
        if db.validate(self.email.text, self.password.text):
            MainWindow.current = self.email.text
            self.reset()
            sm.current = "main"
        else:
            invalidLogin()

    def createBtn(self):
        self.reset()
        sm.current = "create"

    def reset(self):
        self.email.text = ""
        self.password.text = ""

class WindowManager(ScreenManager):
    pass

sm = WindowManager()

screens = [LoginWindow(name="login"), CreateAccountWindow(name="create"), MainWindow(name="main")]
for screen in screens:
    sm.add_widget(screen)

sm.current = "login"

class FrameWork(App):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = "DeepPurple"
    title = "Frame Work"

    def build(self):
        return sm

design.kv:

<WindowManager>:
    LoginWindow:
        name: "login"

        email: email
        password: password
        MDRaisedButton:
           pos_hint:{"x":0.2,"y":0.05}
           size_hint: 0.6, 0.2
           font_size: (root.width**2 + root.height**2) / 13**4
           text: "Login"
           on_release:
              root.manager.transition.direction = "up"
              root.loginBtn()
Traceback (most recent call last):
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\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\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivymd\elevation.py", line 118, in _update_shadow
     self._shadow = App.get_running_app().theme_cls.quad_shadow
 AttributeError: 'NoneType' object has no attribute 'theme_cls'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "C:/Users/tsuyu/PycharmProjects/waverunners-ocr/venv/Scripts/framedesign.py", line 132, in <module>
     sm = WindowManager()
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\screenmanager.py", line 968, in __init__
     super(ScreenManager, self).__init__(**kwargs)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\floatlayout.py", line 65, in __init__
     super(FloatLayout, self).__init__(**kwargs)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\widget.py", line 361, in __init__
     rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\widget.py", line 469, in apply_class_lang_rules
     rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 538, in apply
     rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 659, in _apply_rule
     child, crule, rootrule, rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 659, in _apply_rule
     child, crule, rootrule, rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 657, in _apply_rule
     root=rctx['ids']['root'], rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\uix\widget.py", line 469, in apply_class_lang_rules
     rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 538, in apply
     rule_children=rule_children)
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivy\lang\builder.py", line 707, in _apply_rule
     e), cause=tb)
 kivy.lang.builder.BuilderException: Parser: File "<inline>", line 58:
 ...
      56:
      57:    lbl_txt: lbl_txt
 >>   58:    height: dp(36) if not root._height else root._height
      59:    width: lbl_txt.texture_size[0] + root.increment_width
      60:    padding: (dp(8), 0)
 ...
 AttributeError: 'NoneType' object has no attribute 'theme_cls'
   File "C:\Users\tsuyu\PycharmProjects\waverunners-ocr\venv\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\tsuyu\PycharmProjects\waverunners-ocr\venv\lib\site-packages\kivymd\elevation.py", line 118, in _update_shadow
     self._shadow = App.get_running_app().theme_cls.quad_shadow

回答1:


Root cause of problem

The problem was because theme_cls was not defined when instantiating WindowManager object, sm = WindowManager().

Solution

The solution is to instantiate the WindowManager() after instantiated theme_cls = ThemeManager().

py file

  • Replace return sm with returnWindowManager()`
  • Remove the following lines of code and implement add_widget() (aka instantiate children) in kv file

    sm = WindowManager()
    
    screens = [LoginWindow(name="login"), CreateAccountWindow(name="create"), MainWindow(name="main")]
    for screen in screens:
        sm.add_widget(screen)
    
    sm.current = "login"
    

Snippets - py file

class WindowManager(ScreenManager):
    pass


class FrameWork(App):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = "DeepPurple"
    title = "Frame Work"

    def build(self):
        return WindowManager()

kv file

  • Instantiate the screens (CreateAccountWindow, and MainWindow)as children of class rule, <WindowManager>:

Snippets - kv file

<WindowManager>:
    LoginWindow:
        name: "login"
    CreateAccountWindow:
        name: "create"
    MainWindow:
        name: "main"

Example

The following example is a mock-up of your app using Kivy (ScreenManager, Screen, Label, Popup, FloatLayout, GridLayout) and KivyMD (e.g. ThemeManager, MDLabel, MDTextField, MDRaisedButton, MDRectangleFlatButton).

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty

from kivymd.theming import ThemeManager

from database import DataBase as db

Builder.load_string("""
#:import MDLabel kivymd.label.MDLabel
#:import MDTextField kivymd.textfields.MDTextField
#:import MDRaisedButton kivymd.button.MDRaisedButton
#:import MDRectangleFlatButton kivymd.button.MDRectangleFlatButton

<WindowManager>:
    LoginWindow:
        name: "login"
    CreateAccountWindow:
        name: "create"
    MainWindow:
        name: "main"

<LoginWindow>:        

    namee: namee
    email: email
    password: passw
    bikebrand: bikebrand

    FloatLayout:

        FloatLayout:
            size: root.width, root.height/2

            MDLabel:
                text: "Create an Account"
                size_hint: 0.8, 0.2
                pos_hint: {"x":0.1, "top":1}
                font_size: (root.width**2 + root.height**2) / 14**4

            MDLabel:
                size_hint: 0.26,0.15
                pos_hint: {"x":0, "top":0.8}
                text: "Name: "
                font_size: (root.width**2 + root.height**2) / 14**4

            MDTextField:
                helper_text: "Name"
                helper_text_mode: "on_focus"
                pos_hint: {"x":0.3, "top":0.76}
                size_hint: 0.5, 0.08
                id: namee
                multiline: False
                font_size: (root.width**2 + root.height**2) / 14**4

            MDLabel:
                size_hint: 0.26,0.15
                pos_hint: {"x":0, "top":0.7}
                text: "Email: "
                font_size: (root.width**2 + root.height**2) / 14**4

            MDTextField:
                helper_text: "e.g. john.doe@gmail.com"
                helper_text_mode: "on_focus"
                pos_hint: {"x":0.3, "top":0.66}
                size_hint: 0.5, 0.08
                id: email
                multiline: False
                font_size: (root.width**2 + root.height**2) / 14**4

            MDLabel:
                size_hint: 0.2,0.15
                pos_hint: {"x":0, "top":0.6}
                text: "Password: "
                font_size: (root.width**2 + root.height**2) / 14**4

            MDTextField:            
                helper_text: "Must contain Symbols:( e.g. @#$% ), Numbers:( e.g. 123456 ), Lowercase Characters:( e.g. abcdefgh ) and Uppercase Characters:( e.g. ABCDEFGH )"
                helper_text_mode: "on_focus"
                pos_hint: {"x":0.3, "top":0.56}
                size_hint: 0.5, 0.08
                id: passw
                multiline: False
                password: True
                font_size: (root.width**2 + root.height**2) / 14**4

            MDLabel:
                size_hint: 0.26,0.15
                pos_hint: {"x":0, "top":0.5}
                text: "Bike: "
                font_size: (root.width**2 + root.height**2) / 14**4

            Spinner:
                id: bikebrand
                on_text:
                    print("kv: bikebrand.text={}".format(bikebrand.text))
                text: "<Select>"
                values: ['Brand A', 'Brand B', 'Brand C', 'Brand D', 'Brand E', 'Brand F', 'Brand G', 'Brand H', 'Brand I']
                # background_color: 1,1,1,1
                color: 0,0,0,1
                color_down: 0,0,0,1
                size_hint: 0.5, 0.08
                pos_hint: {"x":0.3, "top":0.46}

            MDRectangleFlatButton:
                pos_hint:{"x":0.3,"y":0.25}
                size_hint: 0.5, 0.1
                font_size: (root.width**2 + root.height**2) / 15**4
                text: "Already have an Account? Log In"
                background_color: 0.68, 0.8, 0.5, 0.18
                color: 0,0,0,1
                on_release:
                    root.manager.transition.direction = "left"
                    root.loginBtn()

            MDRaisedButton:
                pos_hint:{"x":0.2,"y":0.05}
                size_hint: 0.6, 0.2
                font_size: (root.width**2 + root.height**2) / 13**4
                text: "Create Account"
                on_release:
                    root.manager.transition.direction = "up"
                    root.createBtn()

<CreateAccountWindow>:
    GridLayout:
        cols: 1

        MDRaisedButton:
            text: 'Goto MainWindow'
            on_release: root.manager.current = 'main'

        MDLabel:
            text: 'Create Account Window'
            font_size: sp(50)

<MainWindow>:
    GridLayout:
        cols: 1

        MDRaisedButton:
            text: 'Goto LoginWindow'
            on_release: root.manager.current = 'login'

        MDLabel:
            text: 'Main Window'
            font_size: sp(50)

""")


def invalidLogin():
    pop = Popup(title='Invalid Login',
                content=Label(text='Invalid username or password.'),
                size_hint=(None, None), size=(400, 400))
    pop.open()


def invalidForm():
    pop = Popup(title='Invalid Form',
                content=Label(text='Please fill in all inputs with valid information.'),
                size_hint=(None, None), size=(400, 400))

    pop.open()


class LoginWindow(Screen):
    email = ObjectProperty(None)
    password = ObjectProperty(None)

    def loginBtn(self):
        self._shadow = App.get_running_app().theme_cls.quad_shadow
        print(f"\nloginBtn: self._shadow={self._shadow}")

        if db.validate(self.email.text, self.password.text):
            MainWindow.current = self.email.text
            self.reset()
            self.manager.current = "main"
        else:
            invalidLogin()

    def createBtn(self):
        self.reset()
        self.manager.current = "create"

    def reset(self):
        self.email.text = ""
        self.password.text = ""


class CreateAccountWindow(Screen):
    pass


class MainWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass


class FrameWork(App):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = "DeepPurple"
    title = "Frame Work"

    def build(self):
        return WindowManager()


if __name__ == "__main__":
    FrameWork().run()

Output



来源:https://stackoverflow.com/questions/57129106/error-in-update-shadow-self-shadow-app-get-running-app-theme-cls-quad-sha

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!