必须在所有类中使用Kivy属性吗?

时间:2014-05-29 15:53:13

标签: python kivy

经典常识编程表示将GUI代码与核心处理分开。我在Kivy开始这种方式,但在我的第一轮原型中遇到了问题。

deck.py

class Card:
    def __init__(self, suit, value):
        self.name = "%s %s" % (suit, value)

main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from deck import Card

class CardDisplay(BoxLayout):

    card = ObjectProperty(Card("Default", 0))


class BoardDisplay(BoxLayout):
    board = [[Card("Player1", 1),
              Card("Player1", 2),
              Card("Player1", 3),
              Card("Player1", 4)],
             [Card("Player2", 1),
              Card("Player2", 2),
              Card("Player2", 3),
              Card("Player2", 4)]]

class GameApp(App):
    pass

if __name__ in ("__main__", "__android__"):
    GameApp().run()

game.kv

BoardDisplay:
    orientation: "vertical"

    BoxLayout:
        CardDisplay:
            card: root.board[0][0]
        CardDisplay:
            card: root.board[0][1]
        CardDisplay:
            card: root.board[0][2]
        CardDisplay:
            card: root.board[0][3]

    BoxLayout:
        CardDisplay:
            card: root.board[1][0]
        CardDisplay:
            card: root.board[1][1]
        CardDisplay:
            card: root.board[1][2]
        CardDisplay:
            card: root.board[1][3]


<CardDisplay>:
    Label:
        text: root.card.name

运行这个,我按预期得到一张8张牌,但所有牌都是&#34;默认0&#34;。我认为这是因为我使用的是root.card.name,它不是StringProperty,而只是card类的一个属性。但是......有什么更好的方法呢?我是否真的应该在每个包含我想要显示的内容(在本例中为Card)的类中继承Widget(或其类似内容)?或者是否有一种我无法理解的约束方法?我通读了Kivy的文档并且可以发誓它提到了这样的问题,但是我无法再找到这个参考...

1 个答案:

答案 0 :(得分:2)

问题是root.card.name不是Property,所以当你指定它时(text: root.card.name),Kivy不知道绑定任何东西。绑定在kv中自动发生,但并不完美。所以这是一个简单的解决方法:

<CardDisplay>:
    Label:
        text: root.card and root.card.name

表达式root.card and root.card.name的结果将是root.card.name的值,假设已分配root.card。但是,当Kivy读取该任务时,它会发现您正在使用root.card并且会正确绑定。

使用属性的关键是知道何时需要通知更新。您不需要root.card.name成为StringProperty,除非您想知道该属性何时更新。换句话说,如果您更改Card使用的CardDisplay实例,则会更新Label。但是,如果您只是更新name的{​​{1}}属性,则Card更新。

但是,这同样适用于Label上的board属性。更新此属性不会更新显示,因为BoardDisplay不是属性。但Kivy可以处理列表列表并提供有关更新的通知:

board

这样您就可以收到通知。

哦,有一件事我忘了提一下:如果你确实需要使用非board1 = ListProperty([Card("Player1", i) for i in range(4)]) board2 = ListProperty([Card("Player2", i) for i in range(4)]) board = ReferenceListProperty(board1, board2) 上的属性(如Widget),你可以从Card扩展到获取属性工作。 Kivy不仅仅是一个UI,它还是一个框架。在非UI代码中使用Kivy是可以的。如果您在.NET中使用过数据绑定,则可以将EventDispatcher视为WidgetControl,将UIElement视为EventDispatcher