我正在处理两个文件
- test.py
- 测试.kv
test.py的内容如下:
import kivy
kivy.require('1.0.0')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_file("test.kv")
class MainScreen(Screen):
def __init__(self, *args, **kwargs):
super(MainScreen, self).__init__(*args, **kwargs)
def printIds(self):
print self.ids
def printChildren(self):
print self.ids.box.children
for child in self.ids.box.children:
print child.text, child.id
def addButton(self):
self.ids.box.add_widget(Button(text = "newly added Button", id = "test_button_id"))
pass
class MyApp(App):
def __init__(self,*args, **kwargs):
super(MyApp, self).__init__(*args, **kwargs)
def build(self):
app = MainScreen()
return app
if __name__ == '__main__':
MyApp().run()
test.kv的内容为:
<MainScreen>:
BoxLayout:
orientation: "horizontal"
id: box
Label:
text: "test label"
id: test_label_id
Button:
text: "Print Children"
on_release: root.printChildren()
Button:
text: "Print ids"
on_release: root.printIds()
Button:
text: "Add Button"
on_release: root.addButton()
我的问题如下:我想通过python文件中的self.ids命令访问新添加的按钮(当按下按钮添加按钮调用函数addButton时会添加它)。但当我这样做时(即按下按钮打印id),它只显示我在kivy文件中分配的id,即:box(它是BoxLayout的id)和test_label_id(它是测试标签的id)。
我想错了吗?我的意思是,如果我用self.ids.box.add_widged(Button(text="...", id="..."))
命令在python文件中添加一个按钮,它应该可以通过self.ids
命令看到,对吧?
我也可以从另一个方向测试这一点:如果我打印boxlayout
的所有子项,并用命令child.text
或child.id
获取它们的例如文本和id,它会向我显示新添加的按钮的文本和id以及其他按钮/标签的文本,但不会显示我在kivy文件中分配的id(特别是:它会为它们显示None)。
我是不是做错了什么?
ID仅在kvlang中创建,并且这样的操作(Button(id='something')
)不能以常见的方式使用:
Button:
id: my_id
它不会将ID存储在父级的ids
字典中。然而,您可以使用一些巧妙的技巧修改父级的ids
字典(它只是一个"可观察的"字典),但最终您需要将对小部件的引用设置为弱/proxy字典,否则小部件不会被垃圾收集。
一个更好的想法是,在kv中为您的小部件创建一些容器,并将其children
属性与索引一起使用,或者创建一个自定义属性,同时循环其父级并检查自定义属性的值,或者类似于以下内容:
# in App class
class X(App):
my_widgets = DictProperty()
# in custom widget init
def __init__(self, **kwargs):
super(<class name>, self).__init__(**kwargs)
app = App.get_running_app()
app.my_widgets['my_new_widget'] = WeakProxy(Button())
参考WeakProxy
.:)