You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MDDropdownMenu实现递归动态选单时遇到的问题(续)

解决MDDropdownMenu的AttributeError并实现递归动态选择功能

看起来你遇到的AttributeError: 'super' object has no attribute '__getattr__'主要是因为在App的__init__方法过早访问kv部件的ids,而且你的逻辑位置不符合需求。我们把所有下拉菜单的逻辑移到Address类里,同时实现国家-州的动态联动,下面是完整的解决方案:

错误原因分析

  1. 你在MainApp的__init__里直接访问self.kv.ids.field,但此时kv文件的部件还没完成初始化,导致找不到对应的部件,触发了属性错误。
  2. 原代码没有把逻辑放在Address类中,不符合你的需求;同时缺少州选择的UI和联动逻辑。

修改后的代码实现

Python文件

from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivymd.uix.menu import MDDropdownMenu
from kivy.clock import Clock

class Address:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 定义国家和对应的州数据
        self.country_state_data = {
            'Japan': ['Tokyo', 'Chiba', 'Kanto'],
            'Australia': ['New South Wales', 'Victoria', 'Queensland'],
            'Canada': ['Ontario', 'Quebec', 'British Columbia']
        }
        
        # 初始化国家菜单
        self._init_country_menu()
        # 初始化州菜单(初始为空,选完国家后更新)
        self._init_state_menu()

    def _init_country_menu(self):
        # 创建国家菜单选项
        country_items = [{"text": country} for country in self.country_state_data.keys()]
        self.country_menu = MDDropdownMenu(
            caller=self.ids.country_field,
            items=country_items,
            position="bottom",
            width_mult=3
        )
        self.country_menu.bind(on_release=self.on_country_selected)

    def _init_state_menu(self):
        # 初始州菜单为空,选完国家后更新
        self.state_menu = MDDropdownMenu(
            caller=self.ids.state_field,
            items=[],
            position="bottom",
            width_mult=3
        )
        self.state_menu.bind(on_release=self.on_state_selected)

    def on_country_selected(self, instance_menu, instance_menu_item):
        def set_country(interval):
            # 设置国家输入框文本
            self.ids.country_field.text = instance_menu_item.text
            instance_menu.dismiss()
            # 更新州菜单的选项
            self._update_state_menu(instance_menu_item.text)
        Clock.schedule_once(set_country, 0.1)

    def _update_state_menu(self, selected_country):
        # 根据选中的国家获取对应的州列表
        states = self.country_state_data.get(selected_country, [])
        # 更新州菜单的选项
        state_items = [{"text": state} for state in states]
        self.state_menu.items = state_items

    def on_state_selected(self, instance_menu, instance_menu_item):
        def set_state(interval):
            self.ids.state_field.text = instance_menu_item.text
            instance_menu.dismiss()
        Clock.schedule_once(set_state, 0.1)

    def submit(self):
        # 这里可以添加提交逻辑
        country = self.ids.country_field.text
        state = self.ids.state_field.text
        print(f"提交的地址:国家={country},州={state}")

class MainApp(MDApp):
    def build(self):
        return Builder.load_file('../Files/Myapp.kv')

if __name__ == '__main__':
    MainApp().run()

Kivy文件(Myapp.kv)

<Address@MDScreen>:
    md_bg_color : [102/255,153/255,153/255,1]
    MDCard :
        size_hint : None, None
        size : 300, 450
        pos_hint : {"center_x":.5,"center_y":.5}
        elevation : 15
        md_bg_color : [157/255,159/255,48/255,1]
        padding : 20
        spacing : 30
        orientation : "vertical"
        
        MDTextField:
            id: country_field
            pos_hint: {'center_x': .5, 'center_y': .5}
            size_hint_x: None
            width: "200dp"
            hint_text: "Choose Country"
            required: True
            helper_text_mode: "on_error"
            on_focus: if self.focus: root.country_menu.open()
        
        MDTextField:
            id: state_field
            pos_hint: {'center_x': .5, 'center_y': .5}
            size_hint_x: None
            width: "200dp"
            hint_text: "Choose State"
            required: True
            helper_text_mode: "on_error"
            on_focus: if self.focus and root.ids.country_field.text: root.state_menu.open()
        
        MDRoundFlatButton :
            text : 'Submit'
            pos_hint : {'center_x':0.5, 'center_y':0.5}
            font_size : 20
            text_color: 0, 0, 0, 1  # 修正原代码的text_color为可见颜色
            on_release: root.submit()
        
        Widget :
            size_hint_y : None
            height : 30

# 设置根部件为Address
Address:

关键改进点

  • 逻辑迁移:把所有下拉菜单的创建、事件绑定、联动逻辑都移到了Address类中,完全符合你的需求。
  • 动态联动:选中国家后,自动更新州菜单的选项,实现递归动态选择。
  • 错误修复:移除了MainApp中过早访问部件ids的代码,通过在Address类的__init__中初始化菜单,确保部件已完成初始化。
  • UI完善:添加了州选择的TextField,修复了提交按钮的文字颜色不可见的问题。
  • 数据结构:用字典存储国家-州的映射关系,方便后续扩展更多国家和州。

内容的提问来源于stack exchange,提问作者Biju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:02:49