Kivy and gradient fills

2,928 views
Skip to first unread message

Eric

unread,
Sep 1, 2012, 12:14:03 PM9/1/12
to kivy-...@googlegroups.com
Is using opengl and a fbo the only way to make a rectangle with a gradient fill in Kivy?  That is, there is no simpler way, is there?  I'm trying to build some realistic Android UI components, such as the action bar, and many of the default Android themes use a gradient fill.  I'm new to opengl, so it's not clear to me how else to approach this problem.  Is there a simple way to use texture coordinates to achieve an even gradient fill for a canvas rectangle?

It would be really nice to abstract out a 'gradient' property for canvas, although I know that would be tricky to implement.

Thanks for your input.

Eric

tshirtman

unread,
Sep 1, 2012, 2:34:08 PM9/1/12
to kivy-...@googlegroups.com
Well, you can create texture with just your colors, and abuse the opengl behaviour that will automatically create a gradient if the texture is displayed bigger than it's size:

https://gist.github.com/3582544

here i create a two pixel texture, and then put it on a 200x200 rect, and i get a two color gradient. :)

i used code from this page of the doc http://kivy.org/docs/api-kivy.graphics.texture.html#kivy.graphics.texture.Texture

Eric

unread,
Sep 1, 2012, 3:14:06 PM9/1/12
to kivy-...@googlegroups.com
Great example.  And yes, I see now that I missed the existing gradient example in the documentation under "Blitting custom data": http://kivy.org/docs/api-kivy.graphics.texture.html#blitting-custom-data

This is perfect for what I need.  Thanks so much for your help.

Tim H.

unread,
Sep 4, 2014, 9:21:24 AM9/4/14
to kivy-...@googlegroups.com
A small useful code snippet for that:

class Gradient(object):
    @staticmethod
    def horizontal(rgba_left, rgba_right):
        texture = Texture.create(size=(2, 1), colorfmt="rgba")
        pixels = rgba_left + rgba_right
        pixels = [chr(int(v * 255)) for v in pixels]
        buf = ''.join(pixels)
        texture.blit_buffer(buf, colorfmt='rgba', bufferfmt='ubyte')
        return texture

    @staticmethod
    def vertical(rgba_top, rgba_bottom):
        texture = Texture.create(size=(1, 2), colorfmt="rgba")
        pixels = rgba_bottom + rgba_top
        pixels = [chr(int(v * 255)) for v in pixels]
        buf = ''.join(pixels)
        texture.blit_buffer(buf, colorfmt='rgba', bufferfmt='ubyte')
        return texture

and then in .kv:

#:import Gradient your_module.Gradient

canvas:
    Rectangle:
        size: self.size
        pos: self.pos
        texture: Gradient.horizontal((0, 0, 0, 1), (1, 1, 1, 1))

Pierre Boulanger

unread,
Sep 10, 2014, 7:14:32 AM9/10/14
to kivy-...@googlegroups.com
Hi Tim,

I'm sorry for my english but i'ts not my mother langage...

I test your snippet but finally i have an this return:
"NameError: name 'Gradient' is not defined"

here's my main.py:
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Rectangle, Color


class Menu(Screen):
    pass

class Degrade(App):
        def build(self):
             sm = ScreenManager()
             sm.add_widget(Menu(name='menu'))
  
             return sm

if __name__ == "__main__":
       Degrade().run()


my kv:
# : import Gradient.Gradient
<Menu>
 
    canvas.before:
        Rectangle:
            source: 'background.png'
            pos: self.pos
           size: self.size 
           texture: Gradient.horizontal((0,0,0,1),(1,1,1,1))

I don't understanding why this....

geek...@mgmiller.net

unread,
Oct 21, 2016, 5:52:08 PM10/21/16
to Kivy users support
The line below is broken.

geek...@mgmiller.net

unread,
Oct 21, 2016, 6:01:40 PM10/21/16
to Kivy users support
Cool.  I've updated it to Python 3 and extended it to take an arbitrary number of arguments:

from itertools import chain

from kivy.graphics.texture import Texture


class Gradient(object):

    @staticmethod
    def horizontal(*args):
        texture = Texture.create(size=(len(args), 1), colorfmt='rgba')
        buf = bytes([ int(v * 255)  for v in chain(*args) ])  # flattens

        texture.blit_buffer(buf, colorfmt='rgba', bufferfmt='ubyte')
        return texture

    @staticmethod
    def vertical(*args):
        texture = Texture.create(size=(1, len(args)), colorfmt='rgba')
        buf = bytes([ int(v * 255)  for v in chain(*args) ])  # flattens
Reply all
Reply to author
Forward
0 new messages