Python 如何在kivy中将文本颜色设置为渐变纹理?

Python 如何在kivy中将文本颜色设置为渐变纹理?,python,kivy,Python,Kivy,我曾经使用渐变色创建纹理,并将其设置为标签、按钮等的背景。但我想知道如何将其设置为标签的颜色?您不能将颜色属性设置为渐变,这不是它的功能。应使用直接应用于画布顶点说明的图像或纹理来实现渐变。听起来像一个有趣的谜题。下面是我的想法: from kivy.lang import Builder from kivy.graphics.texture import Texture from kivy.properties import ObjectProperty, ListProperty from

我曾经使用渐变色创建
纹理
,并将其设置为
标签
按钮
等的背景。但我想知道如何将其设置为
标签
颜色

您不能将
颜色
属性设置为渐变,这不是它的功能。应使用直接应用于画布顶点说明的图像或纹理来实现渐变。

听起来像一个有趣的谜题。下面是我的想法:

from kivy.lang import Builder
from kivy.graphics.texture import Texture
from kivy.properties import ObjectProperty, ListProperty
from kivy.uix.label import Label


class LabelGradient(Label):
    gradient = ObjectProperty(None)
    bg_color = ListProperty([0, 0, 0, 255])

    def __init__(self, **kwargs):
        super(LabelGradient, self).__init__(**kwargs)

        # bind to texture to trigger use of gradient
        self.bind(texture=self.fix_texture)

    def fix_texture(self, instance, texture):
        if self.gradient is None:
            return

        # unbind, so we don't loop
        self.unbind(texture=self.fix_texture)

        # The normal Label texture is transparent except for the text itself
        # This code changes the texture to make the text transparent, and everything else
        # gets set to self.bg_color (a property of LabelGradient)
        pixels = list(self.texture.pixels)
        for index in range(3, len(pixels)-4, 4):
            if pixels[index] == 0:
                # change transparent pixels to the bg_color
                pixels[index-3:index+1] = self.bg_color
            else:
                # make the text itself transparent
                pixels[index] = 0

        # create a new texture, blit the new pixels, and apply the new texture
        new_texture = Texture.create(size=self.texture.size, colorfmt='rgba')
        new_texture.blit_buffer(bytes(pixels), colorfmt='rgba', bufferfmt='ubyte')
        new_texture.flip_vertical()
        self.texture = new_texture

Builder.load_string('''
<LabelGradient>:
    canvas.before:
        # draw the gradient below the normal Label Texture
        Color:
            rgba: 1,1,1,1
        Rectangle:
            texture: self.gradient
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
''')


if __name__ == '__main__':
    from kivy.app import App
    from kivy.lang import Builder

    class LabelGradientApp(App):
        grad = ObjectProperty(None)

        def build(self):
            # create a 64x64 texture, defaults to rgba / ubyte
            self.grad = Texture.create(size=(64, 64))

            # create 64x64 rgb tab, and fill with values from 0 to 255
            # we'll have a gradient from black to white
            size = 64 * 64 * 3
            buf = bytes([int(x * 255 / size) for x in range(size)])

            # then blit the buffer
            self.grad.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
            return theRoot

    app = LabelGradientApp()

    theRoot = Builder.load_string('''
FloatLayout:
    LabelGradient:
        text: 'Abba Dabba Doo'
        font_size: 30
        gradient: app.grad
''')

    app.run()
来自kivy.lang导入生成器
从kivy.graphics.texture导入纹理
从kivy.properties导入ObjectProperty,ListProperty
从kivy.uix.label导入标签
类别标签梯度(标签):
渐变=对象属性(无)
bg_color=ListProperty([0,0,0,255])
定义初始(自我,**kwargs):
超级(LabelGradient,self)。\uuuuu初始值(**kwargs)
#绑定到纹理以触发渐变的使用
self.bind(纹理=self.fix\u纹理)
def fix_纹理(自身、实例、纹理):
如果self.gradient为“无”:
返回
#解开束缚,这样我们就不会循环
self.unbind(纹理=self.fix\u纹理)
#除文本本身外,法线标签纹理是透明的
#此代码更改纹理以使文本和其他所有内容透明
#获取设置为self.bg_color(LabelGradient的属性)
像素=列表(self.texture.pixels)
对于范围内的索引(3,len(像素)-4,4):
如果像素[索引]==0:
#将透明像素更改为bg_颜色
像素[index-3:index+1]=self.bg\u颜色
其他:
#使文本本身透明
像素[索引]=0
#创建新纹理,blit新像素,然后应用新纹理
新建纹理=纹理。创建(大小=self.texture.size,colorfmt='rgba')
新的\u纹理.blit\u缓冲区(字节(像素),colorfmt='rgba',bufferfmt='ubyte')
新建纹理。翻转垂直()
self.texture=新纹理
Builder.load_字符串(“”)
:
在以下情况之前:
#在法线标签纹理下方绘制渐变
颜色:
rgba:1,1,1,1
矩形:
纹理:自梯度
大小:self.texture\u大小
位置:int(self.center\u x-self.texture\u size[0]/2]),int(self.center\u y-self.texture\u size[1]/2.)
''')
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
从kivy.app导入应用程序
从kivy.lang导入生成器
类别标签GradientApp(应用程序):
梯度=对象属性(无)
def生成(自):
#创建64x64纹理,默认为rgba/ubyte
self.grad=Texture.create(大小=(64,64))
#创建64x64 rgb选项卡,并填充0到255之间的值
#我们将有一个从黑色到白色的渐变
尺寸=64*64*3
buf=字节([int(x*255/大小)表示范围内的x(大小)])
#然后,快速缓冲
自梯度blit_缓冲区(buf、colorfmt='rgb',bufferfmt='ubyte')
回根
app=LabelGradientApp()
theRoot=Builder.load\u字符串(“”)
浮动布局:
标签梯度:
文字:“阿巴·达巴·杜”
字体大小:30
梯度:app.grad
''')
app.run()
我的方法是使文本透明,并在文本后面绘制渐变。 由
标签
创建的正常
纹理
是透明的,实际文本除外

上面的
标签渐变
扩展了
标签
,并使用
kv
中的
规则绘制渐变。
fix\u texture()
方法绑定到
标签
纹理
属性,因此一旦创建了
纹理
,就会调用该方法。
fix\u texture()
方法使实际文本透明,并将
纹理的其余部分设置为
bg\u颜色