Search code examples
pythonkivy

How to customize style.kv in Kivy


According to Kivy Doc, I can customize a kivy app look, by creating a local style.kv file that will be use instead of standard. So I edited the original file, by modifying, the behavior of the Button widget like this :

<-Button,-ToggleButton>:
    canvas:
        Color:
            rgba: [1, 0, 0, 1] if self.state == 'normal' else [0, 0, 1, 1]
        Rectangle:
            pos: self.pos
            size: self.size
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            texture: self.texture
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)

I was hoping that buttons background's become red and change to blue when clicked. But nothings happen, and the default behavior was applied.

This is the content of my main file

from os.path import abspath, dirname, join

from kivy.app import App
from kivy.resources import resource_add_path, resource_find
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button


class MainLayout(BoxLayout):
    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)
        self.add_widget(Button(text="Button1"))
        self.add_widget(Button(text="Button2"))

class MainApp(App):
    def build(self):
        return MainLayout()


if __name__ == '__main__':
    res_path = join(dirname(abspath(__file__)), "custom")
    resource_add_path(res_path)
    print("find ", resource_find("data/style.kv"))
    MainApp().run()

At runtime, the local path of the style.kv is well printed.

All help is greatly appreciated!


Solution

  • Even though the documentation says that you can customize kivy exactly the way you have attempted, it does not look like it works. However, you can get it to work by just loading your modified style.kv using kivy.lang.Builder. For example:

    from kivy.lang import Builder
    
    Builder.load_string('''
    <-Button,-ToggleButton>:
        canvas:
            Color:
                rgba: [1, 0, 0, 1] if self.state == 'normal' else [0, 0, 1, 1]
            Rectangle:
                pos: self.pos
                size: self.size
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                texture: self.texture
                size: self.texture_size
                pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
    ''')
    
    from os.path import abspath, dirname, join
    
    from kivy.app import App
    from kivy.resources import resource_add_path, resource_find
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button
    
    
    class MainLayout(BoxLayout):
        def __init__(self, **kwargs):
            super(MainLayout, self).__init__(**kwargs)
            self.add_widget(Button(text="Button1"))
            self.add_widget(Button(text="Button2"))
    
    class MainApp(App):
        def build(self):
            return MainLayout()
    
    if __name__ == '__main__':
        MainApp().run()