如何通过在Kivy Python中调用函数来设置小部件属性?

如何通过在Kivy Python中调用函数来设置小部件属性?,python,kivy,Python,Kivy,假设在我的RootWidget中有一个ThemeManager对象作为class属性,如下所示: class RootWidget(Widget): theme = ThemeManager() 管理器定义了一个返回十六进制颜色的函数 class ThemeManager: def get_color(self): return '#ffffffff' 假设我使用kv文件在RootWidget中创建了一个按钮。如何从kv文件调用管理器函数?以下是一个不

假设在我的
RootWidget
中有一个
ThemeManager
对象作为class属性,如下所示:

class RootWidget(Widget):
    theme = ThemeManager()
管理器定义了一个返回十六进制颜色的函数

class ThemeManager:    
    def get_color(self):
        return '#ffffffff'
假设我使用
kv
文件在
RootWidget
中创建了一个
按钮。如何从
kv
文件调用
管理器
函数?以下是一个不起作用的示例:

import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.lang import Builder


class ThemeManager:
    def get_color(self):
        return '#ffffffff'


class RootWidget(Widget):
    theme = ThemeManager()


my_kv = Builder.load_string("""
#: import get_color_from_hex kivy.utils.get_color_from_hex
RootWidget:
    Button:
        color: get_color_from_hex(app.root.theme.get_color())
        text: "Test"
""")


class TestApp(App):
    def build(self):
        return my_kv

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

既然你的问题已经得到了回答,这里有一个解释,其实很简单(我想)

在按钮尝试读取函数时,app.root为None。因为事情的顺序是(松散的):-

  • 创建了RootWidget
  • 一旦它和它的所有子对象都完成(initcompleted),对象就会被传递到build()中的行
  • app.root仅在调用TestApp.run()时设置
  • 至于为什么。发生这种情况时,app.py中的init方法将self.root初始化为None。然后可以通过load_kv(加载与此应用同名的kv)或run(大多数情况下都是这样)进行设置

    因此,您可以在on_press事件中调用app.root(因为这些事件仅在完全创建应用程序时响应用户交互),而不是在一次性小部件初始化事件中


    有趣的是,root在app.py中没有定义为ObjectProperty,这意味着你不能像绑定标题和图标那样绑定到其中的更改。不确定它是否会改变,所以这可能是没有意义的。

    root.theme
    替换
    app.root.theme
    。@Nykakin:哇,昨天我花了一整天的时间尝试我能想到的一切!谢谢如果有人能解释一下简单使用
    root
    app.root
    之间的区别,我会把它标记为答案。谢谢。这是有道理的。我猜事件调度员必须通过应用程序,事后看来,这一点现在很明显。