Search code examples
pythonimagebuttonkivy

Buttons with image using Kivy (Python)


I am trying to use Kivy to create two buttons. Each one with a picture. The first one would show an image of the string “b1” and the other an image of the string “b2”. But instead of the expected result, I see this:

enter image description here

from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

class MyApp(App):
    def build(self):
        layout = BoxLayout(orientation='horizontal', spacing=0, padding=0)

      
        img01 = Image(source=path1, allow_stretch=True, keep_ratio=False)
        btn01 = Button(size_hint=(None, None), background_normal='', background_down='')
        

        
        btn01.width = img01.texture_size[0]
        btn01.height = img01.texture_size[1]
        img01.size = btn01.size
        img02 = Image(source=path2, allow_stretch=True, keep_ratio=False)
        btn02 = Button(size_hint=(None, None), background_normal='', background_down='')
        

        btn02.width = img02.texture_size[0]
        btn02.height = img02.texture_size[1]
        img02.size = btn02.size

        btn01.bind(on_press=self.on_image_click01)
        btn02.bind(on_press=self.on_image_click02)

        layout.add_widget(btn01)
        layout.add_widget(btn02)
        btn01.add_widget(img01)
        btn02.add_widget(img02)

        return layout

    def on_image_click01(self, instance):
        print("Click 1", instance.children[0].source)

    def on_image_click02(self, instance):
        print("Click 2", instance.children[0].source)

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

Solution

  • When you set the Image to be a child of the Button, there is no control over the size/pos of the Image, because the Button is not intended to be a container for other Widgets. So both Images get the default pos of (0, 0) and the size that you assign.

    You can use the background_normal and/or background_down properties of the Button instead of an Image Widget, like this:

    from kivy.app import App
    from kivy.uix.button import Button
    from kivy.uix.boxlayout import BoxLayout
    
    
    class MyApp(App):
        def build(self):
            layout = BoxLayout(orientation='horizontal', spacing=0, padding=0)
            btn01 = Button(background_normal=path1)
            btn02 = Button(background_normal=path2)
    
            btn01.bind(on_press=self.on_image_click01)
            btn02.bind(on_press=self.on_image_click02)
    
            layout.add_widget(btn01)
            layout.add_widget(btn02)
    
            return layout
    
        def on_image_click01(self, instance):
            print("Click 1", instance.background_normal)
    
        def on_image_click02(self, instance):
            print("Click 2", instance.background_normal)
    
    
    if __name__ == '__main__':
        MyApp().run()