我是Kivy的新手,这里有一小段演示代码,展示了我的问题:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
class KivyGuiApp(App):
def build(self):
return root_widget
class MyBox(BoxLayout):
def print_ids(self, *args):
print("\nids:")
for widget in self.walk():
print("{} -> {}".format(widget, widget.id))
def print_names(self, *args):
print("\nnames:")
for widget in self.walk():
print("{} -> {}".format(widget, widget.name))
root_widget = Builder.load_string("""
MyBox:
id: screen_manager
name: 'screen_manager'
SimpleLayout:
id: simple_layout
name: 'simple_layout'
<SimpleLayout@BoxLayout>:
id: simple_layout_rule
name: 'simple_layout_rule'
Button:
id: button_ids
name: 'button_ids'
text: 'print ids to console'
on_release: app.root.print_ids()
Button:
id: button_names
name: 'button_names'
text: 'print names to console'
on_release: app.root.print_names()
""")
if __name__ == '__main__':
KivyGuiApp().run()
当您运行代码时,将会有两个按钮:
- 第一个按钮用于遍历所有小部件并打印它们的名称(按预期工作 - 对于每个小部件返回“name”),
- 第二个按钮也会遍历所有小部件,但不是打印名称,而是打印其id(它不起作用 - 对于每个id都返回None)。
- 难道'id'不是像'name'一样的属性吗?
- 我如何从Python侧访问每个小部件的id?
- 我能否通过其id“全局”访问小部件(假设所有id均唯一)?通过“全局”,我的意思是例如(在上面的代码中)从'MyBox:'小部件的id访问而无需引用父子关系,而只是通过ids(或者可能是任何其他对于每个小部件都是唯一的属性)。我正在考虑创建一个字典{id:widget object},其中包含所有窗口小部件以供轻松访问,除非我不知道其他方法? 强调一下 - 我试图避免参考子父方式(当您想要稍后更改小部件树时这种方式相当混乱),我想在.kv语言中生成小部件。 那么最好的方法是什么?
这是我能想到的通过唯一“全局”id引用小部件的最简单方法。
首先,我创建了一个将由我的应用程序类继承的类:
class KivyWidgetInterface():
''' interface for global widget access '''
global_widgets = {}
def register_widget(self, widget_object):
''' registers widget only if it has unique gid '''
if widget_object.gid not in self.global_widgets:
self.global_widgets[widget_object.gid] = widget_object
def get_widget(self, widget_gid):
''' returns widget if it is registered '''
if widget_gid in self.global_widgets:
return self.global_widgets[widget_gid]
else:
return None
因此,只有当小部件具有gid(小部件类变量)并且是唯一的时,才会注册该小部件。这样,我可以仅在此字典中存储关键小部件。而且,从.kv和python两侧都很容易访问。
现在我创建gid变量并在.kv中将它们注册到字典中:
<PickDirectory>:
gid: 'pick_directory'
on_pos: app.register_widget(self)
on_selection: app.get_widget('filelist').some_func()
<FileListView>:
gid: 'filelist'
on_pos: app.register_widget(self)
Button:
name: 'not important'
Button:
gid: 'tab_browse_button1'
on_pos: app.register_widget(self)
我困扰的是,我将我的部件通过'on_pos'事件注册到这个“全局”字典中...我真的不喜欢这样做,但我找不到任何可靠的方法在部件初始化后调用注册方法(当部件被定位并且后来很少调用时,on_pos在init阶段之后立即调用,因此...似乎是以我对kivy api、用.kv语言初始化部件的顺序等知识最不麻烦的方式。如果有更好的方法,我将非常感激任何指针)。无论如何,通过这种方式,我可以轻松地将任何事件绑定到任何类中的任何方法中,直接从.kv文件中进行。
需要记住的一件事是gid(全局id)需要在全局范围内唯一,但我并不觉得这比在本地保持id唯一更令人不安(对我来说可能同样或甚至更加困惑)。正如我所说-我希望以不同的方式注册部件,但我找不到任何其他可靠的方法来做到这一点(而我不认为Clock在这方面是可靠的)。
.apk
文件大小。如果您提供一个简单且“简短”的示例,可能会帮助未来的某个人。但是存储所有小部件可能会成为一种不良习惯,还可能出现某些安全问题。 - Peter Badida