user16240688
user16240688

Reputation:

I made button in Python using KivyMD with a help of some one in this website. It works perfectly for him, but for me something is wrong

App is made with Python 3.9.5, Kivy 2.0.0rc4 and KivyMD 0.104.2. I made KivyMD button. With it you can toggle dark/light mode. But it's printing out error and idk why. I mean, it works for this other guy who helped me on this. But it doesn't work for me. I played around with it a little bit and I've managed to toggle dark/light mode only on this MainWidget class. I want to toggle on the entire app. Here's my Kivy code:

<MainWidget>:

    MDScreen:
        id: screenId
        md_bg_color: 0, 0, 0, 1

    MDIconButton:
        id: light_mode
        icon: "brightness-4"
        user_font_size: "64sp"
        theme_text_color: "Custom"
        text_color: 1, 1, 1, 1
        on_press: app.presser()

And here's my Python code:

class MainWidget(MDFloatLayout):
    pass

class MyApp(MDApp):
    pressed = False

    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.screen_manager = ScreenManager()

        self.mainwidget = MainWidget()
        screen = Screen(name='First')
        screen.add_widget(self.mainwidget)
        self.screen_manager.add_widget(screen)

    def presser(self):
        if self.pressed:
            self.root.ids.light_mode.text_color = 0, 0, 0, 1
            self.root.ids.screenId.md_bg_color = 1, 1, 1, 1
            self.pressed = not self.pressed
        else:
            self.root.ids.light_mode.text_color = 1, 1, 1, 1
            self.root.ids.screenId.md_bg_color = 0, 0, 0, 1
            self.pressed = not self.pressed

And here's the error:

 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:\Users\guram\Desktop\WordBondV.2\main.py", line 815, in <module>
     myapp.run()
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\app.py", line 950, in run
     runTouchApp()
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\base.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\base.py", line 347, in mainloop
     self.idle()
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\base.py", line 391, in idle
     self.dispatch_input()
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\base.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\base.py", line 248, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\core\window\__init__.py", line 1412, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\core\window\__init__.py", line 1428, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\screenmanager.py", line 1198, in on_touch_down
     return super(ScreenManager, self).on_touch_down(touch)
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\relativelayout.py", line 297, in on_touch_down
     ret = super(RelativeLayout, self).on_touch_down(touch)
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivymd\uix\behaviors\ripple_behavior.py", line 255, in on_touch_down
     super().on_touch_down(touch)
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivymd\uix\button.py", line 969, in on_touch_down
     return super().on_touch_down(touch)
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
   File "C:\Users\guram\Desktop\WordBondV.2\venv\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\guram\Desktop\WordBondV.2\my.kv", line 32, in <module>
     on_press: app.presser()
   File "C:\Users\guram\Desktop\WordBondV.2\main.py", line 810, in presser
     self.root.ids.light_mode.text_color = 1, 1, 1, 1
   File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

Upvotes: 1

Views: 443

Answers (2)

XBOT
XBOT

Reputation: 46

There are So Many Errors In Your Code

Don't Worry i solved it for you ;)

Here is the Corrected code :)

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivymd.app import MDApp


kv = """
<MainWidget>:
    screenId: screenId
    light_mode: light_mode
    MDFloatLayout:        
        MDScreen:
            id: screenId
            md_bg_color: 0, 0, 0, 1

        MDIconButton:
            id: light_mode
            icon: "brightness-4"
            user_font_size: "64sp"
            theme_text_color: "Custom"
            text_color: 1, 1, 1, 1
            on_press: root.presser()
"""
Builder.load_string(kv)

sm = ScreenManager()


class MainWidget(Screen):
    pressed = False
    screenId = ObjectProperty(None)
    light_mode = ObjectProperty(None)

    def presser(self):
        if self.pressed:
            self.light_mode.text_color = 0, 0, 0, 1
            self.screenId.md_bg_color = 1, 1, 1, 1
            self.pressed = not self.pressed
        else:
            self.light_mode.text_color = 1, 1, 1, 1
            self.screenId.md_bg_color = 0, 0, 0, 1
            self.pressed = not self.pressed


class MyApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"

        sm.add_widget(MainWidget(name="First"))

        return sm


MyApp().run()

You don't need to use root.ids.widgetid always!

You can define the widget as global widget in your kivy file so that it can be accessed in your python file by using ObjectProperty

Also the best practice is to define all the methods which belong to the specific class in your root class itself :)

Upvotes: 0

watney
watney

Reputation: 141

I'd recommend keeping your root widget inside the kv code so that you can traverse through available id in ids dict. In your code, it's unable to find those ids.

Here's a working version of your code:

I've merged both kivy and python codes in one file but you can obv. separate them and later load your kivy file using Builder.load_file(kivy_file_name)

from kivymd.app import MDApp
from kivymd.uix.floatlayout import MDFloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder

kv="""

ScreenManager:
    Screen:
        name: 'First'
        MainWidget:
            id: my_widget
    
<MainWidget>:

    MDScreen:
        id: screenId
        md_bg_color: 0, 0, 0, 1

    MDIconButton:
        id: light_mode
        icon: "brightness-4"
        user_font_size: "64sp"
        theme_text_color: "Custom"
        text_color: 1, 1, 1, 1
        on_press: app.presser()
"""


class MainWidget(MDFloatLayout):
    pass

class MyApp(MDApp):
    pressed = False

    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.screen_manager = Builder.load_string(kv) # ScreenManager()

        #self.mainwidget = MainWidget()
        #screen = Screen(name='First')
        #screen.add_widget(self.mainwidget)
        #self.screen_manager.add_widget(screen)
        
        return self.screen_manager

    def presser(self):
        if self.pressed:
            self.root.ids.my_widget.ids.light_mode.text_color = 0, 0, 0, 1
            self.root.ids.my_widget.ids.screenId.md_bg_color = 1, 1, 1, 1
            self.pressed = not self.pressed
        else:
            self.root.ids.my_widget.ids.light_mode.text_color = 1, 1, 1, 1
            self.root.ids.my_widget.ids.screenId.md_bg_color = 0, 0, 0, 1
            self.pressed = not self.pressed


if __name__ == '__main__':
    MyApp().run()

Upvotes: 1

Related Questions