【问题标题】:Must Kivy properties be used in all classes?必须在所有类中使用 Kivy 属性吗?
【发布时间】:2014-05-29 15:53:12
【问题描述】:

经典的常识编程将 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 张卡片显示,但所有卡片均为“默认 0”。我认为这是因为我使用的是 root.card.name,它不是 StringProperty,而只是卡片类的一个属性。但是......有什么更好的方法来做到这一点?我真的应该在每个包含我想要显示的东西(在本例中为 Card)的类中从 Widget(或类似的东西)继承吗?还是有我无法理解的绑定方法?我通读了 Kivy 文档,可以发誓它提到了一个像这样的问题,但我无法再次找到参考...

【问题讨论】:

    标签: python kivy


    【解决方案1】:

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

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

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

    使用属性的关键是知道何时希望收到有关更新的通知。您不需要root.card.name 成为StringProperty,除非您想知道该属性何时更新。换句话说,如果您更改CardDisplay 使用的Card 实例,那么它将更新Label。但是,如果您只更新Cardname 属性,Label不会更新。

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

    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),您可以从EventDispatcher 扩展以使属性正常工作。 Kivy 不仅仅是一个 UI,它还是一个框架。在非 UI 代码中使用 Kivy 是可以的。如果您在 .NET 中使用过数据绑定,则可以将Widget 视为ControlUIElement,将EventDispatcher 视为DependencyObject

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 1970-01-01
      • 2018-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多