Kivy: Получить идентификаторы виджетов и доступ к виджетам по уникальному свойству
Я новичок в 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()
Поэтому, когда вы запустите код, появятся две кнопки:
сначала пройтись по всем виджетам и напечатать их имена (которые работают как положено - возвращает «имя» для каждого виджета),вторая кнопка, чтобы также просмотреть все виджеты, но вместо имен выведите их идентификаторы (что не работает - возвращает None для каждого идентификатора).Мои вопросы:
Разве «id» не является таким же свойством, как «name»?Как я могу получить доступ к идентификатору для каждого виджета со стороны Python?Бонусный вопрос:
Могу ли я получить доступ к виджету "глобально" по его идентификатору (при условии, что все идентификаторы уникальны)? Под «глобально» я подразумеваю, например, доступ к (в коде выше) идентификаторам из виджета «MyBox:» без ссылки на parent-child, но только по идентификаторам (или, возможно, любому другому свойству, которое будет уникальным для каждого виджета). Я думал о создании словаря {id: widget object} всех виджетов для легкого доступа, разве есть другой способ, о котором я не знаю? Подчеркну - я стараюсь избегать ссылок по методу children-parent (что довольно грязно, когда вы хотите позже изменить дерево виджетов), и я хотел бы создавать виджеты на языке .kv. Так что будет лучшим способом сделать это?РЕДАКТИРОВАТЬ:
Итак, вот самый простой способ, с помощью которого я мог бы ссылаться на виджеты по уникальному «глобальному» идентификатору.
Сначала я создал класс, который будет наследоваться моим классом приложения:
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 и регистрирую их в dict в .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» ... которое мне действительно не нравится, но я не смог найти надежного способа вызова метода register после виджет был инициализирован (on_pos вызывается сразу после фазы инициализации, когда виджет позиционируется, а позже очень редко, так что ... мне показалось, что этот способ наименее надоедливый, поскольку я знаю kivy api, виджеты заказов инициализируются с помощью .kv язык и т. д., так что, если есть лучший способ, я буду очень любезен для любых указателей).
Во всяком случае, таким образом, я могу легко связать любое событие с любым методом в любом классе прямо из .kv
Следует помнить, что gid (глобальные идентификаторы) должны быть уникальными во всем мире, но я не нахожу это более тревожным, чем сохранение уникальных идентификаторов локально (что может быть одинаково или даже более запутанным для меня). И, как я уже сказал, я бы хотел зарегистрировать виджеты по-другому, но я не смог найти какой-либо другой надежный способ сделать это (и я не считаю, что Clock является надежным для таких вещей).