如何在运行时更改 Kivy 中小部件的颜色?

2022-01-15 00:00:00 python kivy

问题描述

我无法在 Kivy 中更改简单小部件的颜色.我可以在创建小部件时设置颜色,但之后无法更改.

I'm having trouble changing the color of a simple widget in Kivy. I can set the color when I create the widget, but I can't change it afterwards.

这里是简单的布局定义文件circletest.kv.它定义了一个圆圈,其中颜色(实际上只是 r,来自 rgba)、位置和大小都链接到小部件类中的变量.

Here is the simple layout definition file circletest.kv. It defines a circle where the color (actually just the r, from rgba), position and size are all linked to variables in the widget class.

#:kivy 1.4.1

<CircleWidget>:
    canvas:
        Color:
            rgba: self.r,1,1,1
        Ellipse:
            pos: self.pos
            size: self.size

这是应用程序 circletest.py.它创建并显示简单的小部件.创建对象时成功设置颜色和位置.单击小部件时,小部件可以更改它自己的位置,但是当我尝试更改颜色时,什么也没有发生.

Here's the application circletest.py. It creates and displays the simple widget. The color and position are successfully set when the object is created. When the widget is clicked the widget can change it's own position, but when I try to change the color nothing happens.

import kivy
kivy.require('1.4.1')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget

Builder.load_file('circletest.kv')

class CircleWidget(Widget):

    def __init__(s, **kwargs):
        s.size= [50,50]
        s.pos = [100,50]
        s.r = 0
        super(CircleWidget, s).__init__(**kwargs)

    def on_touch_down(s, touch):
        if s.collide_point(touch.x,touch.y):    
            s.pos = [s.pos[1],s.pos[0]]           # This works
            s.r = 1.0                       # <---- This does nothing!

class TestApp(App):

    def build(s):
        parent = Widget()
        w = CircleWidget()
        parent.add_widget(w)
        return parent

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

谁能看出问题所在?

更新

仍然不确定这个问题的答案是什么,但我确实有一个解决方法:

Still not sure what the answer to this question is, but I do have a work around:

在 .kv 文件中,我将颜色指向对象中的一个变量.用于提取初始颜色:

In the .kv file I pointed the color to a variable in my object. Works for extracting the initial color:

Color:
    rgba: self.col

当我想从 .py 文件中更改颜色时,我会遍历画布中的所有指令并修改颜色"类型的第一个指令.显然这是一种 hack,并且不适用于具有多个 Color: 属性的小部件:

When I want to change the color from the .py file I loop through all the instructions in the canvas and modify the first one of type "Color". Obviously this is a hack, and won't work on widgets with more than one Color: property:

for i in s.canvas.get_group(None):
    if type(i) is Color:
        i.r, i.g, i.b, i.a = v
        break

我将所有内容封装在一个属性中,这样使用起来很整洁:

I wrapped that all up in a property so it's neat to use:

class CircleWidget(Widget):

    def get_col(s):
        return s._col

    def set_col(s,v):
        for i in s.canvas.get_group(None):
            if type(i) is Color:
                i.r, i.g, i.b, i.a = v
                break
        s._col = v

    col = property(get_col, set_col)

    def __init__(s, **kwargs):
        s.size= [50,50]
        s.pos = [100,50]
        s._col = (1,1,0,1)
        super(CircleWidget, s).__init__(**kwargs)

    def on_touch_down(s, touch):
        if s.collide_point(touch.x,touch.y):    
            s.col = (s.col[::-1]) # Set to some other color

目前似乎可以使用.如果您知道更好的方法,请告诉我.我确信一定有一个更简单的方法,而且我遗漏了一些明显的东西!

Seems to work for now. Please let me know if you know a better way of doing this. I'm sure there must be a simpler way, and that I'm missing something obvious!


解决方案

在您的初始版本中,您只是缺少属性声明

In your initial version, you were just missing the declaration of the property

from kivy.properties import NumericProperty

在标题和

r = NumericProperty(0)

就在class CircleWidget(Widget)下:

另外,您声明您的 kv 文件名为 circletest.kv,但您的应用程序名为 TestApp,因此您应该更改其中一个以使其连贯,否则将找不到您的 kv 文件,但您不这样做'不要报告任何问题,我想这只是问题中的错字.刚刚看到 Builder.load_file ok,

also, you state that your kv file is named circletest.kv, but your app is named TestApp, so you should change one of them to make them coherent, or your kv file won't be found, but as you don't report any issue with that, i guess it's only a typo in the question. edit: just saw the Builder.load_file ok,

干杯.

相关文章