Kivy自定义按钮按下时更改画布颜色

3

回答您之前的问题后,我已经查看了相关文档和示例,尝试修改自定义按钮在按下时的画布颜色。以下是我的代码,但是无论点击多少次都没有任何变化:

class CircularButton(ButtonBehavior, Label):

    # code inspired from:
        # https://github.com/kivy/kivy/issues/4263#issuecomment-217430358
        # https://stackoverflow.com/a/42886979/6924364
        # https://blog.kivy.org/2014/10/updating-canvas-instructions-declared-in-python/

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

        with self.canvas.before:
            Color(rgba=(.5,.5,.5,.5))
            self.shape = Ellipse(pos=self.pos,size=self.size)

        self.bind(pos=self.update_shape, size=self.update_shape)

    def update_shape(self, *args):
        self.shape.pos = self.pos
        self.shape.size = self.size

    def on_press(self, *args): #<--- what am I doing wrong here?
        with self.canvas:
            Color(rgba=(0,0,0,0))

    def collide_point(self, x, y):
        return Vector(x, y).distance(self.center) <= self.width / 2
2个回答

4

您需要存储和重复使用颜色指令,并在Canvas添加指令时更改颜色。在您的情况下,您正在添加一个新的颜色指令,但它不适用于其他元素(如矩形或椭圆),因此您看不到效果。

from kivy.base import runTouchApp
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
from kivy.vector import Vector
from kivy.graphics import Color, Ellipse
from kivy.properties import ListProperty


class CircularButton(ButtonBehavior, Label):
    background_color = ListProperty((0.5,.5,.5,.5))

    def __init__(self, **kwargs):
        super(CircularButton,self).__init__(**kwargs)
        self.draw()
        self.text='test'

    def update_shape(self, *args):
        self.shape.pos = self.pos
        self.shape.size = self.size

    def on_background_color(self, *args):
        self.shape_color.rgba = self.background_color

    def draw(self, *args):
        with self.canvas.before:
            self.shape_color = Color(rgba=(0.5,.5,.5,.5))
            self.shape = Ellipse(pos=self.pos,size=self.size)
            self.bind(pos=self.update_shape, size=self.update_shape)

    def on_press(self, *args):
        self.background_color= (1, 0, 0, 1)

    def on_release(self, *arg):
        self.background_color = (0.5,.5,.5,.5)

    def collide_point(self, x, y):
        return Vector(x, y).distance(self.center) <= self.width / 2

if __name__ == '__main__':
    runTouchApp(CircularButton())

虽然我更喜欢将.kv和.py文件组合在一起,但利用kv语言是声明性的,使连接变得简单:

from kivy.base import runTouchApp
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
from kivy.vector import Vector
from kivy.lang import Builder


Builder.load_string('''
<CircularButton>
    background_color: 0.5,.5,.5,.5
    canvas.before:
        Color:
            rgba: self.background_color
        Ellipse:
            pos: self.pos
            size: self.size
    ''')


class CircularButton(ButtonBehavior, Label):
    def __init__(self, **kwargs):
        super(CircularButton, self).__init__(**kwargs)
        self.text = "test"

    def on_press(self, *args):
        self.background_color = (1, 0, 0, 1)

    def collide_point(self, x, y):
        return Vector(x, y).distance(self.center) <= self.width / 2

if __name__ == '__main__':
    runTouchApp(CircularButton())

太好了!我尝试添加on_release函数来将颜色重置为.5,.5,.5,.5,但它只会使红色变暗,而不是回到灰色。为什么? - Justapigeon
@Justapigeon 试试第二种方法,我会找出第一种方法失败的原因。 - eyllanesc
有趣的是,当我检查画布时,颜色对象的RGBA值是1.0、1.0、1.0、1.0,尽管已经指定了颜色。 - Justapigeon
1
@Justapigeon 我已经更新了我的答案,之前有些混淆认为画布(canvas)会清除先前的内容,但这并不是真的。我已经添加了重用它的部分,并在我的更新答案中指示了。请测试一下,告诉我你是否还有错误。 - eyllanesc
天才!谢谢! - Justapigeon
我已经寻找了一个星期的答案来解决这个完全相同的问题!感谢您花时间为我们解决它。 - Gabriel Freundt-Thurne

2
也许这个解决方案可以帮助某些人:

.py

(注:.py是Python代码文件的扩展名)
class PositionButton(Button):
    b_color = ListProperty()

.kv

<PositionButton>:
    background_color: [0,0,0,0]
    b_color: [0, 0, 1, .3] if self.state == 'normal' else [0, 0, 1, .5]
    canvas.before:
        Color:
            rgba: self.b_color

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接