Kivy 外部规则继承 2

Kivy outside rule inherence 2

作为后续问题:

main.py

import os
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.properties import ObjectProperty


class FancyButton(Button):
    imp = ObjectProperty(None)


class Important(StackLayout):

    font_kanji = os.path.join('fonts', 'TakaoPMincho.ttf')

    def NoInspiration(self, smile):
        print("Received: {}".format(smile))

    def AddFancy(self):
        print(self.ids)
        temp = FancyButton(text='f', imp = self)
        self.ids.boxy.add_widget(temp)


class TestApp(App):
    def build(self):
        pass

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

test.kv

#:kivy 1.9.0

<FancyButton>:
    font_name: self.imp.font_kanji  # ERROR
    on_release: self.imp.NoInspiration(':)')  # WORKS


<Important>:
    id: imp

    BoxLayout:
        id: boxy
        orientation: 'vertical'

        FancyButton:
            text: "smiley"
            imp: root

        Button:
            text: "add fancy"
            on_release: imp.AddFancy()


BoxLayout:
    Important

在上面的例子中 'on_release: self.imp.NoInspiration(':)')' 有效是因为 FancyButton 有 'imp: root'.

但是 'font_name: self.imp.font_kanji' 不起作用并给出错误:

AttributeError: 'NoneType' object has no attribute 'font_kanji'

我的猜测是,on_release 发生在所有小部件加载之后,直接 font_name,所以没有 'imp: root'。

我也试过:

font_kanji = StringProperty(os.path.join('fonts', 'TakaoPMincho.ttf'))

,但无济于事。

问题

如何让 font_name 引用 font_kanji?我应该使用全局吗?如果是,您将如何在 Python 中设置一个可以在 .kv 中访问的全局?

(如果我将 global 放在 font_Kanji 前面并删除 .kv 文件中的 'self.imp',我会收到错误消息:“NameError: name 'font_kanji' is not defined”)

您的猜测是正确的:创建按钮时,其 imp 属性 是 None。解决这个问题的方法是观察 imp 属性 并在其处理程序中设置 font_name 的值:

class FancyButton(Button):
    imp = ObjectProperty(None)

    def on_imp(self, obj, imp):
        if imp:
            self.font_name = imp.font_kanji

这种方式是在 imp 属性 使用适当的 Important 实例初始化后设置字体。这种方法的缺点是 Instance.font_kanji 的变化不会触发 FancyButton.font_name.

的变化

如果你想绑定两个属性,那么你必须从 Instance.font_kanji 端调用 bind 函数(因为我们想对其变化做出反应)以动态创建 FancyButton实例:

class Important(StackLayout):
    font_kanji = os.path.join('fonts', 'TakaoPMincho.ttf')

    def NoInspiration(self, smile):
        print("Received: {}".format(smile))

    def AddFancy(self):
        temp = FancyButton(text='f', imp = self)
        self.bind(font_kanji=temp.setter('font_name'))
        self.ids.boxy.add_widget(temp)

kv语言定义的接口可以直接绑定:

<Important>:
    id: imp

    BoxLayout:
        id: boxy
        orientation: 'vertical'

        FancyButton:
            text: "smiley"
            font_name: root.font_kanji
            imp: root

        Button:
            text: "add fancy"
            on_release: imp.AddFancy()
''')