Как мне изменить цвет моего виджета в Kivy во время выполнения?

У меня проблемы с изменением цвета простого виджета в Kivy. Я могу установить цвет при создании виджета, но потом не могу его изменить.

Вот файл определения простого макета circletest.kv. Он определяет круг, в котором цвет (на самом деле просто r, из rgba), положение и размер связаны с переменными в классе виджетов.

#:kivy 1.4.1

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

Вот приложение circletest.py. Он создает и отображает простой виджет. Цвет и положение успешно установлены при создании объекта. При нажатии на виджет виджет может изменить свою собственную позицию, но когда я пытаюсь изменить цвет, ничего не происходит.

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()

Кто-нибудь может увидеть проблему?

UPDATE

До сих пор не уверен, что ответ на этот вопрос, но у меня есть обходной путь:

В файле .kv я указал цвет на переменную в моем объекте. Работы по извлечению исходного цвета:

Color:
    rgba: self.col

Когда я хочу изменить цвет из файла .py, я перебираю все инструкции на холсте и изменяю первый тип «Цвет». Очевидно, что это хак, и он не будет работать с виджетами с более чем одним свойством Color::

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

Я завернул все это в свойство, чтобы его было удобно использовать:

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

Кажется, сейчас работает. Пожалуйста, дайте мне знать, если вы знаете лучший способ сделать это. Я уверен, что должен быть более простой способ, и что я упускаю что-то очевидное!

17 голосов | спросил Andy 21 +04002012-10-21T15:49:16+04:00312012bEurope/MoscowSun, 21 Oct 2012 15:49:16 +0400 2012, 15:49:16

2 ответа


0

В вашей первоначальной версии вы просто пропустили объявление свойства

from kivy.properties import NumericProperty

в заголовке и

r = NumericProperty(0)

прямо под class CircleWidget(Widget):

Кроме того, вы заявляете, что ваш файл kv называется circletest.kv, но ваше приложение называется TestApp, поэтому вы должны изменить один из них, чтобы сделать его согласованным, иначе ваш файл kv не будет найден, но по мере не сообщайте о каких-либо проблемах с этим, я думаю, это всего лишь опечатка в вопросе. редактировать: только что увидел Builder.load_file хорошо,

приветствий.

ответил Tshirtman 22 +04002012-10-22T13:19:59+04:00312012bEurope/MoscowMon, 22 Oct 2012 13:19:59 +0400 2012, 13:19:59
0

Ответ от tshirtman правильный, вот объяснение того, что происходит.

В вашем файле kv, когда вы установите

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

Строка rgba: self.r, 1, 1, 1 пытается обновить значение rgba всякий раз, когда происходит изменение значения r. Это делается неявно в языке kv с помощью привязки, что можно сделать с помощью свойства kivy , так как оно реализует Шаблон наблюдателя .

Переменная r в вашем коде была обновлена, но это просто переменная, которая не дает никаких признаков того, что ее значение изменилось и не может быть связано с. Если вы заметили, что ваши изменения в pos работают, потому что pos является свойством ReferenceListProperty.

Общее правило для программирования в Kivy, если вы хотите изменить код в зависимости от свойства виджета /объекта, используйте Недвижимость Киви . Он предоставляет вам возможность Наблюдать за изменениями свойств и соответственно корректировать свой код либо явно через bind / on_property_name или неявно через язык kv, как упомянуто выше.

ответил qua-non 22 +04002012-10-22T14:58:48+04:00312012bEurope/MoscowMon, 22 Oct 2012 14:58:48 +0400 2012, 14:58:48

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132