#python #python-3.x #kivy #keyerror #kivymd
#python #python-3.x #kivy #ошибка ключа #kivymd
Вопрос:
Я пытаюсь изменить свое существующее приложение Kivy, чтобы включить красивые виджеты KivyMD. Я удалил a Spinner
для MDRaisedButton
on_release
caller
with для MDDropdownMenu
списка имен устройств, которые были сопряжены через Bluetooth с устройством (в зависимости от платформы). Для этого тестового примера я использую только список пунктов меню, как показано в MDDropdownMenu
примере документов.
По какой-то причине я получаю KeyError: 'dev_button'
MDRaisedButton
id
сообщение о инициализации MDDropdownMenu
свойств. __init__
Метод находится в моем корневом классе, который находится в отдельных файлах с именем indexui.py
и indexui.kv
в файле main.py
and main.kv
. Но импортируется в main.py
файл и включается в main.kv
файл. Приложение действительно запускалось перед изменением Spinner
.
indexui.py
class RootLay(FloatLayout):
this = ObjectProperty(None) # App object
bserial = ObjectProperty(None) # Bluetooth variables starts
recv_stream = ObjectProperty(None)
send_stream = ObjectProperty(None)
menu = ObjectProperty(None)
rfsocket = ObjectProperty(None)
device = ObjectProperty(None)
pattern = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.device = None
self.pattern = re.compile(r'[GNSTUkg,s]')
self.dev_list = []
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
print(dir(self.ids))
self.menu = MDDropdownMenu(
caller=self.ids.dev_button, items=menu_items, width_mult=4
)
self.menu.bind(on_release=self.menu_callback)
indexui.kv
<RootLay>:
MDToolbar:
pos_hint: {'top': 1, 'right': 1}
title: "Bluetooth Weigh"
MDRaisedButton:
id: dev_button
text: "SEE DEVICES"
pos_hint: {'top': 0.76, 'right': 0.9}
on_release: app.root.menu.open()
main.py
from kivymd.app import MDApp
from views.indexui import RootLay
from kivy.properties import ObjectProperty
class MainApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Yellow" # "Purple", "Red"
self.theme_cls.primary_hue = "600"
# self.icon = 'bluetooth-connected_326502.png'
root = ObjectProperty(RootLay())
return root
def on_pause(self):
return True
MainApp().run()
main.kv
#:include views/indexui.kv
RootLay:
Может кто-нибудь, пожалуйста, помочь мне понять, почему существует KeyError
? MDRaisedButton
Находится в RootLay
области видимости класса как метод. Поэтому я должен иметь доступ ко всем его свойствам.
Комментарии:
1. Похоже, что ваш
kv
файл не загружается. Вы явно загружаетеkv
? вашkv
файл названmain.kv
?2. Привет, спасибо за ваш ответ. Да, я считаю, что он загружается, поскольку
main.kv
файл имеет то же имя, что и класс приложения. Я добавил кодkv
файлов выше. Есть ли что-то, что я должен сделать дополнительно? Или что-то, что я импортирую неправильно?
Ответ №1:
Я считаю, что проблема в том, что вы пытаетесь получить доступ к ids
RootLay
классу до того, как они станут доступны. Я предлагаю отложить этот доступ, используя Clock.schedule_once()
следующее:
class RootLay(FloatLayout):
this = ObjectProperty(None) # App object
bserial = ObjectProperty(None) # Bluetooth variables starts
recv_stream = ObjectProperty(None)
send_stream = ObjectProperty(None)
menu = ObjectProperty(None)
rfsocket = ObjectProperty(None)
device = ObjectProperty(None)
pattern = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.device = None
self.pattern = re.compile(r'[GNSTUkg,s]')
self.dev_list = []
Clock.schedule_once(self.setup_menu) # delay until ids are available
def setup_menu(self, dt):
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
self.menu = MDDropdownMenu(
caller=self.ids.dev_button,
items=menu_items,
width_mult=4
)
self.menu.bind(on_release=self.menu_callback)
Комментарии:
1. Это очень умное решение. Спасибо!
2. Если вы добавите функцию обратного вызова в
menu_items
и не привязываете ее, как в моем примере, повлияет ли это на работу функции или нет?3. Это
menu_items=[{'callback': self.menu_callback, 'text': f"Item {i}"} for i in range(5)}]
вместо того, чтобы привязывать его кself.menu
.4. Причина, по которой я спрашиваю, заключается в том, что Эрик Сандберг создал пример, используя
callback
таким образом, но он не работает, когдаcallback
для andviewclass
установленitems
ключ. Он работает только тогда, когда для него установленcallback
ключ вMDDropdownMenu
экземпляре. ВMDDropdownMenu
исходном коде я также не нахожуviewclass
илиcallback
, который может быть установлен дляitems
ключаMDDropdownMenu
экземпляра. Так что, возможно, он устарел,5. Я не знаю ни одного способа включить обратный вызов в
items
список, однако вы можете добавитьcallback=self.menu_callback
кMDDropdownMenu()
вызову (и удалитьself.menu.bind
вызов).