Search code examples
pythonfunctioncanvascolorskivy

How to change canvas colour in Kivy using id:?


Been looking around and can't seem to find any solid information about changing a canvas colour in Kivy by referencing an id:. My goal here is to create a light and a dark theme for my app wherein the user changes it in app settings. Here is my .kv code at the moment:

themescreen.kv

<ThemeScreen>:
    id: theme_canvas
    canvas:
        Color:
            rgb: utils.get_color_from_hex("#161D39")
        Rectangle:
            size: self.size
            pos: self.pos
    FloatLayout:
        RoundedButton:
            id: dark_theme
            text: "Dark"
            pos_hint:  {"top": .5, "center_x": .5}
            size_hint: .38, .08
            padding: 20, 20
            opacity: 1 if self.state == 'normal' else .5
            on_release:
                app.change_theme("#000523")
        RoundedButton:
            id: light_theme
            text: "Light"
            pos_hint:  {"top": .3, "center_x": .5}
            size_hint: .38, .08
            padding: 20, 20
            opacity: 1 if self.state == 'normal' else .5
            on_release:
                app.change_theme("#C4CCFF")

And so what I'm trying to do is run the function that will change out my hex colours to the appropriate theme. Below is my .py function.

    def change_theme(self, theme):
        theme_canvas = self.root.ids["theme_screen"].ids["theme_canvas"]
        theme_canvas.rgb = utils.get_color_from_hex(theme)

I have tried placing the id: in various locations, I've tried having the rgb colour purely in the FloatLayout area and having self.color etc in the canvas then calling that id: instead. At the moment, with this setup I'm getting the error: theme_canvas =self.root.ids["theme_screen"].ids["theme_canvas"] KeyError: 'theme_canvas' And I've tired removing the theme_canvas from the function.

Is there any way this is possible please? I simply want to be able to change the rgb colour via my function. Please help.


Solution

  • There is an alternative solution for your problem

    Since your objective is to change theme while running, you can do this using kivymd (a material design library of kivy)

    You can adjust the theme by using this in the App class

    #light theme
    
    self.theme_cls.theme_style = "Light"
    
    #Dark theme
    self.theme_cls.theme_style = "Dark"
    

    Here is an implementation of this case

    from kivymd.app import MDApp
    from kivy.lang import Builder
    
    Kv="""
    
    BoxLayout:
        Button:
            size_hint:(.1,.1)
            text:'Light theme'
            on_press:
                app.Light()
                
        Button:
            size_hint:(.1,.1)
            text:'Dark theme'
            on_press:
                app.Dark()
    """
    class Main(MDApp):
        def build(self):
            
            return Builder.load_string(Kv)
                
                                            
        def Light(self):
            
            self.theme_cls.theme_style = "Light"
            return Builder.load_string(Kv)
            
        def Dark(self):
            
            self.theme_cls.theme_style = "Dark"
            return Builder.load_string(Kv)
            
    Main().run()
    
    
    

    By default kivymd theme will be set to "Light"

    You can find more about Kivymd theming at https://kivymd.readthedocs.io/en/latest/themes/theming/index.html