Search code examples
pythonbackgroundkivygradient

How to make gradient background in Kivy


I am trying to create an app with gradient background and label in Kivy. I googled and found this for gradient background, but it is only widget and when I trying to put label there it is not working. Code:

from kivy.app import App, runTouchApp
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.app import App
from kivy.uix.label import Label


class MyWidget(Widget):
    def __init__(self, **args):
        super(MyWidget, self).__init__(**args)
        self.texture = Texture.create(size=(2, 2), colorfmt='rgba')
        p1_color = [173, 0, 255, 255]
        p2_color = [253, 0, 243, 255]
        p3_color = [173, 0, 255, 255]
        p4_color = [253, 0, 243, 255]
        p = p1_color + p2_color + p3_color + p4_color
        buf = bytes(p)
        self.texture.blit_buffer(buf, colorfmt='rgba', bufferfmt='ubyte')
        with self.canvas:
            self.rect = Rectangle(pos=self.pos, size=self.size, texture=self.texture)

        self.bind(size=self.update_rect)
        self.bind(pos=self.update_rect)

    def update_rect(self, *args):
        self.rect.size = self.size
        self.rect.pos = self.pos


runTouchApp(Builder.load_string('''
MyWidget:
'''))

From this code, I tried to create an app with gradient background, but it is black(

from kivy.app import App, runTouchApp
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.app import App
from kivy.uix.label import Label

class TestApp(App):
    def build(self):
        self.texture = Texture.create(size=(2, 2), colorfmt='rgba')
        p1_color = [173, 0, 255, 255]
        p2_color = [253, 0, 243, 255]
        p3_color = [173, 0, 255, 255]
        p4_color = [253, 0, 243, 255]
        p = p1_color + p2_color + p3_color + p4_color
        buf = bytes(p)
        self.texture.blit_buffer(buf, colorfmt='rgba', bufferfmt='ubyte')

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

Over background I need to create a label, but I don't know why I can't(
Help please)


Solution

  • One approach to solving this problem can be using Color and Line in the canvas of background layout.

    In order to make a gradient effect, I added as many vertical lines as the application window width to the background which is a BoxLayout in my case. In every iteration, the variable of alpha_channel_rate has been increased. And that makes the gradient effect.

    from kivy.app import App
    from kivy.core.window import Window
    from kivy.graphics import Line, Color
    from kivy.uix.boxlayout import BoxLayout
    
    
    class Background(BoxLayout):
        def __init__(self):
            super(Background, self).__init__()
            self.width = Window.size[0]
            self.height = Window.size[1]
            self.add_gradient()
    
        def add_gradient(self):
            alpha_channel_rate = 0
            increase_rate = 1 / self.width
    
            for sep in range(self.width):
                self.canvas.add(Color(rgba=(0, 1, 0, alpha_channel_rate)))
                self.canvas.add(Line(points=[sep, 0, sep, self.height], width=1))
                alpha_channel_rate += increase_rate
    
    
    class GradientApp(App):
        def build(self):
            background = Background()
            return background
    
    
    if __name__ == "__main__":
        GradientApp().run()
    

    The output of the program is like this: enter image description here

    Maybe you can create some other functionality that you want using this method. For instance, a radial gradient effect also can be created using the Circle method of the kivy.graphics.

    On the other hand, the lines and color objects can be dynamic using the bind method as you did in your program, and also some gradient groups can be created using canvas instructions in order to edit some canvas objects in later times.