michaD
michaD

Reputation: 65

kivy: decorate setter-function (EventDispatcher)

The following kv-code places an image inside a button and scales it, depending on the button's size:

   Button:                                                                          
    text:'Katze'                                                                 
    background_color: ('#00ffff')                                                
    font_size: 32                                                                
    on_press:root.playSound(self)                                                
    Image:                                                                       
        source: './katze.png'                                                    
        center_x: self.parent.center_x                                           
        center_y: self.parent.center_y                                           
        size: root.width*0.25, root.height*0.25

Is there a way to reproduce this in python?

I have an approximate solution with the help of this post kivy widgets : multiple buttons, centering, get window/screen dimensions, now my question is:

Can I decorate the setter functions (below) of the image objects so that the length and width parameters can be changed? For example, to a quarter of their values? I am new to Python and have spent some time trying to understand the decorator principle, but have not yet been able to find a solution.

def build(self):
    self.layout = GridLayout(cols=3, spacing=10)
    for animal in self.zoo:
        knopf = ButtonID(
            id = animal, #member ButtonID(Button)
            background_color=get_color_from_hex(self.zoo[animal][0]),
            on_press =  self.playSound,                             
        )
        self.layout.add_widget(knopf)
        
        bild=Image()
        knopf.add_widget(bild)
        bild.source=self.animal[tier][2]
                                                               
        knopf.bind(center=bild.setter('center'))
        #knopf.bind(width=bild.setter('width'))                                                     
        #knopf.bind(height=bild.setter('height'))                                                   
        knopf.bind(size=bild.setter('size'))

    return self.layout

Greetings, michael

Upvotes: 0

Views: 46

Answers (1)

michaD
michaD

Reputation: 65

After studying the decorator concept, I found a solution. Here is the source code for automatically generated buttons with embedded images, which are always nicely scaled via bindings and a decorator.

This program shows buttons with animal icons. When you press the buttons, a sound file with the corresponding animal voice is played. Served as motivation in a programming course on kivy. Was a lot of fun.

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.utils import get_color_from_hex
from kivy.core.audio import SoundLoader
from kivy.lang import Builder

import sys

class ButtonID(Button):
    def __init__(self, id, **kwargs):
        super(Button, self).__init__(**kwargs)
        self.id=id

    def update(self, *kargs):
        print("groesse: ", self.size)
        print("position: ", self.pos)
        #self.canvas.clear() 
        with self.canvas:
            pass
        
class ZooApp(App):

    zoo = {"Vogel":["00FFFF", "./birds_cardinal.mp3","./vogel.png"],
           "Katze":["DDA0DD", "./cat_meow_04.mp3","./katze.png"],
           "Kuh":["E2DDD5", "./cows_two_cows_mooing.mp3","./kuh.png"],
           "Esel":["FFFF00", "./donkey_braying.mp3","./esel.png"],
           "Schwein":["FFD700", "./pig_grunt.mp3","./schwein.png"],
           "Schaf":["FF8C00", "./sheep_bleat_001.mp3","./schaf.png"],
           "Lanz":["E2DDD5","./lanz_bulldog_trim.mp3","./lanzFrei.png"]}

    def playSound(self, button):
        SoundLoader.load(filename=self.zoo[button.id][1]).play()
        
    def build(self):
        self.title = "Kleintier-Zoo"
        self.layout = GridLayout(cols =3, spacing = 10) 
        for tier in self.zoo:
            knopf = ButtonID(
                id = tier,
                background_color = get_color_from_hex(self.zoo[tier][0]),
                on_press =  self.playSound, # play-sound = callback-fkt
            )

            self.layout.add_widget(knopf)

            bild=Image()

            knopf.add_widget(bild)
            bild.source=self.zoo[tier][2]
                
            def dekorateur(func):
                def wrapper(*args, **kwargs):
                    erstes=args[0] #scheint button-id zu sein
                    zweites=args[1]
                    zweites=zweites/2
                    args=(erstes,zweites)
                    print("args: ", erstes, zweites)
                    print("kwargs: ", kwargs)
                    return func(*args, **kwargs)
                return wrapper

            knopf.bind(center=bild.setter('center'))
            
            setterfunktion = bild.setter('width')
            setterfunktion=dekorateur(setterfunktion)
            knopf.bind(width=setterfunktion)

            setterfunktion = bild.setter('height')
            setterfunktion=dekorateur(setterfunktion)
            knopf.bind(height=setterfunktion)

            
        return self.layout
        
if __name__ == "__main__":
    ZooApp().run()

Upvotes: 0

Related Questions