1

how does one change the opacity of the randomly thrown image when the buttons are clicked? (using kivy).

from random import randint
from random import random
from kivy.app import App 
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.graphics import Color, Line, Rectangle
from kivy.uix.filechooser import FileChooserListView, FileChooserIconView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout



class MyBackground(Widget):

    def __init__(self, **kwargs):
        x = randint(1,10)
        print (x)
        y = 'water.png'
        if x==1:
            y = 'a.png'
        if x==2:
            y = 'b.png'
        if x==3:
            y = 'c.png'
        if x==4:
            y = 'd.png'
        if x==5:
            y = 'e.png'
        if x==6:
            y = 'f.png'
        if x==7:
            y = 'g.png'
        if x==8:
            y = 'h.png'
        if x==9:
            y = 'i.png'
        if x==10:
            y = 'j.png'
        super(MyBackground, self).__init__(**kwargs)
        with self.canvas:
            Color(1, 1, 1, 0.5)
            self.bg = Rectangle(source=y, pos=self.pos, size=self.size)
        self.bind(pos=self.update_bg)
        self.bind(size=self.update_bg)
        Color(1, 0, 1, 0.5)

    def update_bg(self, *args):
        self.bg.pos = self.pos
        self.bg.size = self.size


class MyPaintWidget(Widget):
    def on_touch_down(self, touch):
        with self.canvas:
            Color(1, 1, 1)
            d = 30.
            touch.ud['line'] = Line(points=(touch.x, touch.y))

    def on_touch_move(self, touch):
        touch.ud['line'].points += [touch.x, touch.y]

class MyRandomApp(App):

    def build(self):
        layout = BoxLayout(spacing=10, orientation='vertical')
        b = BoxLayout(spacing=0)
        btn1 = Button(text='opacity 40%', size_hint=(.2, .2))
        btn3 = Button(text='opacity 20%', size_hint=(.2, .2))
        btn4 = Button(text='opacity 10%', size_hint=(.2, .2))
        btn5 = Button(text='opacity 0%', size_hint=(.2, .2))
        b.add_widget(btn1)
        b.add_widget(btn3)
        b.add_widget(btn4)
        b.add_widget(btn5)
        layout.add_widget(b)
        background = MyBackground(size_hint=(1, 10))
        layout.add_widget(background)
        painter = MyPaintWidget()
        layout.add_widget(painter)


        return layout



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

I tried to have a definition in the class MyRandomApp(), but it says it has no attribute to canvas.

Cube_tbh
  • 118
  • 1
  • 4
  • 13

1 Answers1

3

I'd suggest using a kivy property in your background widget for opacity, then binding the buttons to a function that updates the opacity.

I also highly suggest looking at the kv language to make this kind of thing easier. It can also help get rid of a lot of the boilerplate code that adds widgets and binds things to other. See kv docs and a good crash course video for more info.

But I'll answer for the way w/o kv. I'm aslo going to remove the random image part for clarity and it really doesn't matter for this example.

First import the import for the property:

from kivy.properties import NumericProperty

Then add a numeric property to your background class. Now you can use that property in the color instruction. Because you are using opacity as a property, kivy will automatically bind it, so when the opacity changes, the Color instruction changes as well. So your background class becomes:

class MyBackground(Widget):
    opacity = NumericProperty(0.5)

    def __init__(self, **kwargs):
        y = 'test.jpg'
        super(MyBackground, self).__init__(**kwargs)
        with self.canvas:
            Color(1, 1, 1, self.opacity)
            self.bg = Rectangle(source=y, pos=self.pos, size=self.size)

        self.bind(pos=self.update_bg)
        self.bind(size=self.update_bg)
        Color(1, 0, 1, 0.5)

    def update_bg(self, *args):
        self.bg.pos = self.pos
        self.bg.size = self.size

Then keep references to the buttons and background widget and connect a function to the button events that updates the opacity of the background widget based on the button pressed. (Note that i'm not a super experienced kivy user, so there might be a better way to determine which button was pressed and self the opacity accordingly.)

So your app becomes: class MyRandomApp(App):

def build(self):
    layout = BoxLayout(spacing=10, orientation='vertical')
    b = BoxLayout(spacing=0)

    self.btn1 = Button(text='opacity 40%', size_hint=(.2, .2))
    self.btn3 = Button(text='opacity 20%', size_hint=(.2, .2))
    self.btn4 = Button(text='opacity 10%', size_hint=(.2, .2))
    self.btn5 = Button(text='opacity 0%', size_hint=(.2, .2))

    b.add_widget(self.btn1)
    b.add_widget(self.btn3)
    b.add_widget(self.btn4)
    b.add_widget(self.btn5)
    layout.add_widget(b)

    self.background = MyBackground(size_hint=(1, 10))

    layout.add_widget(self.background)
    painter = MyPaintWidget()
    layout.add_widget(painter)

    self.btn1.bind(on_press=self.set_opacity)
    self.btn3.bind(on_press=self.set_opacity)
    self.btn4.bind(on_press=self.set_opacity)
    self.btn5.bind(on_press=self.set_opacity)

    return layout

def set_opacity(self,widget):
    if widget is self.btn1:
        self.background.opacity = 0.40
    elif widget is self.btn3:
        self.background.opacity = 0.20
    elif widget is self.btn4:
        self.background.opacity = 0.10
    elif widget is self.btn5:
        self.background.opacity = 0.00
  • This is very helpful. But one question, why do you have to put "self" in front of everything? Thank you! – Cube_tbh May 21 '15 at 02:17
  • Use of the `self` keyword lets you create a class instance attribute. You can then refer to that attribute in other class functions. It's really much deeper than that, and is an important concept in Python. [link](http://stackoverflow.com/questions/2709821/what-is-the-purpose-of-self-in-python) is maybe a place to start – therealpickle May 21 '15 at 02:27