PC端Python Kivy应用添加widget后无响应 MDDropdownMenu重叠问题
问题根因
- 类名引用错误:自定义下拉类命名为
MyListDropdownValue,但在StartScreen.open_listdropdown方法中错误调用了不存在的MyListDropdownProduct类,直接触发运行报错。 - 错误调用
add_widget方法:MDDropdownMenu属于弹出层悬浮组件,本身不需要添加到父布局的控件树中,强制添加会打乱布局结构、破坏组件本身的生命周期管理,是选中选项后应用停止响应的核心原因。 - 实例管理逻辑错误:依赖
self.children长度判断是否新建实例的逻辑不可靠,原布局本身就有默认子控件,会导致后续取children[0]时拿到错误的控件对象,调用方法直接崩溃。 - 嵌套定义冗余:
MyListDropdownValue本身已经继承了MDDropdownMenu,内部不需要再嵌套创建新的MDDropdownMenu实例,多重实例会导致事件响应混乱。
修复方案
核心逻辑是将下拉实例存为StartScreen的类属性管理,不需要添加到布局树,即可避免重复创建实例也不会打乱布局结构,修复后的完整代码如下:
# kivymd 0.104.2 # kivy 2.0.0 from kivy.clock import Clock from kivy.lang import Builder from kivy.metrics import dp from kivy.properties import ObjectProperty from kivymd.app import MDApp from kivy.uix.boxlayout import BoxLayout from kivymd.uix.menu import MDDropdownMenu kv_str = """ <StartScreen>: startscreen_textfield_1: textfield_id BoxLayout: orientation: "vertical" BoxLayout: size_hint: 1, 0.5 BoxLayout: size_hint: 1, 0.5 orientation: "vertical" BoxLayout: MDTextField: id: textfield_id on_text: root.open_listdropdown(textfield_id) BoxLayout: MDTextField: BoxLayout: MDTextField: """ P_LIST = ["ASD", "SDF", "AASD"] def search_product(prefix): return list(filter(lambda l: l.startswith(prefix), P_LIST)) class MyListDropdownValue(MDDropdownMenu): def __init__(self, dropdown_list, **kwargs): super().__init__(caller=dropdown_list, width_mult=5, **kwargs) self.dropdown_list_id = dropdown_list def list_dropdown(self): if len(self.dropdown_list_id.text) == 0: self.dismiss() return prefix = self.dropdown_list_id.text.upper() filtered_list = search_product(prefix) if not filtered_list: self.dismiss() return self.items = [ { 'text': f'{value}', "height": dp(56), "viewclass": "OneLineListItem", "on_release": lambda x=f"{value}": self.set_item(x) } for value in filtered_list ] self.open() def set_item(self, value): def set_item(interval): self.dropdown_list_id.text = value self.dismiss() Clock.schedule_once(set_item, 0.1) class StartScreen(BoxLayout): startscreen_textfield_1 = ObjectProperty() listdropdown = None # 存储下拉实例的属性 def open_listdropdown(self, input_id): # 不存在实例则新建,不用add到布局 if not self.listdropdown: self.listdropdown = MyListDropdownValue(input_id) else: # 存在旧实例先关闭 self.listdropdown.dismiss() # 刷新下拉内容展示 self.listdropdown.list_dropdown() kv = Builder.load_string(kv_str) class Program(MDApp): def build(self): self.screen = StartScreen() return self.screen def main(): app = Program() app.run() if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Алексей Елизаров
相关产品推荐
相关产品推荐

