Python-Kivy:通过self.ids命令引用Label(Button)id(在*.py文件中创建)



我正在处理两个文件

  • 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.textchild.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.:)

最新更新