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

KivyMD动态添加MDDropDownItem触发AttributeError问题求助

动态添加MDDropDownItem触发AttributeError的解决方法

问题场景

使用Python/KivyMD开发UI,需要点击按钮时动态添加MDDropDownItem,而非预先在KV中定义。点击按钮后触发如下错误:

AttributeError: 'super' object has no attribute '__getattr__'

原始代码

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.dropdownitem.dropdownitem import MDDropDownItem


Builder.load_string(
    """    
<View>:
    MDGridLayout:
        rows: 3
        id: layout
        padding: 100, 50, 100, 50
        
        
        MDRaisedButton:
            id: button
            text: 'CREATE DDI'
            on_release: root.Button_On_Click()
        

""")



class View(MDScreen):
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)
        
        
    def Button_On_Click(self):        
        myDdi = MDDropDownItem(
            # size_hint_x = None,
            # width = dp(100),
            # pos_hint = {"right": 1, "center_y": 0.5},
            text = 'SELECT POSITION')
        
        myMenu, scratch = self.Create_DropDown_Widget(myDdi, ['POS 1', 'POS 2', 'POS 3'], width=4)
        myDdi.on_release = lambda: myMenu.open()
        
        self.ids.layout.add_widget(myDdi)
        
       
    def Create_DropDown_Widget(self, drop_down_item, item_list, width):
        items_collection = [
            {
                "viewclass": "OneLineListItem",
                "text": item_list[i],
                "height": self.dp(56),
                "on_release": lambda x = item_list[i], menu=self.Create_DropDown_Widget.__locals__['menu']: self.Set_DropDown_Item(drop_down_item, menu, x),
            } for i in range(len(item_list))
        ]
        
        menu = MDDropdownMenu(caller=drop_down_item, items=items_collection, width_mult=width)
        
        return menu, items_collection

         
    def Set_DropDown_Item(self, drop_down_item, menu, text_item):
        drop_down_item.set_item(text_item)
        menu.dismiss()
        
        


class MainApp(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.View = View()


    def build(self):
        self.title = ' DROP DOWN ITEM ADDED DYNAMICALLY'
        return self.View


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

错误详情

line 49, in Button_On_Click
     text = 'SELECT POSITION')

File "C:\Users\\Miniconda3\lib\site-packages\kivymd\uix\behaviors\declarative_behavior.py", line 311, in __init__
     super().__init__(**kwargs)

File "C:\Users\\Miniconda3\lib\site-packages\kivymd\theming.py", line 1668, in __init__
     super().__init__(**kwargs)

File "C:\Users\\Miniconda3\lib\site-packages\kivy\uix\behaviors\button.py", line 121, in __init__
     super(ButtonBehavior, self).__init__(**kwargs)

File "C:\Users\\Miniconda3\lib\site-packages\kivy\uix\boxlayout.py", line 145, in __init__
     super(BoxLayout, self).__init__(**kwargs)

File "C:\Users\\Miniconda3\lib\site-packages\kivy\uix\layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)

File "C:\Users\\Miniconda3\lib\site-packages\kivy\uix\widget.py", line 357, in __init__
     super(Widget, self).__init__(**kwargs)

File "kivy\_event.pyx", line 262, in kivy._event.EventDispatcher.__init__
File "kivy\properties.pyx", line 520, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 567, in kivy.properties.Property.set
File "kivy\properties.pyx", line 606, in kivy.properties.Property._dispatch
File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1213, in kivy._event.EventObservers._dispatch
File "C:\Users\\Miniconda3\lib\site-packages\kivymd\uix\dropdownitem\dropdownitem.py", line 96, in on_text
     self.ids.label_item.text = text_item

File "kivy\properties.pyx", line 964, in kivy.properties.ObservableDict.__getattr__
 **AttributeError: 'super' object has no attribute '__getattr__'**

问题原因

  1. 组件初始化顺序问题:动态实例化MDDropDownItem时直接设置text属性,会触发on_text方法,但此时MDDropDownItem的内部UI组件(如label_item)还未通过KV解析完成初始化,导致访问self.ids.label_item抛出错误。
  2. 变量捕获错误:Create_DropDown_Widget方法中,列表推导式引用的menu在推导式执行时还未定义,后续点击菜单选项会出现变量引用异常。

修复方案

  1. 延迟设置text属性:先实例化MDDropDownItem,添加到布局后再设置text,确保内部组件已初始化完成。
  2. 修正菜单选项生成逻辑:先创建MDDropdownMenu实例,再基于该实例生成菜单选项,确保lambda能正确捕获menu对象。

修复后的代码

from kivy.lang import Builder
from kivy.metrics import dp
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.dropdownitem.dropdownitem import MDDropDownItem


Builder.load_string(
    """    
<View>:
    MDGridLayout:
        rows: 3
        id: layout
        padding: 100, 50, 100, 50
        
        MDRaisedButton:
            id: button
            text: 'CREATE DDI'
            on_release: root.Button_On_Click()
""")


class View(MDScreen):
    def Button_On_Click(self):        
        # 先实例化,不设置text
        myDdi = MDDropDownItem()
        # 添加到布局后再设置text,确保内部组件已初始化
        self.ids.layout.add_widget(myDdi)
        myDdi.text = 'SELECT POSITION'
        
        myMenu = self.Create_DropDown_Widget(myDdi, ['POS 1', 'POS 2', 'POS 3'], width=4)
        myDdi.on_release = lambda: myMenu.open()
        
       
    def Create_DropDown_Widget(self, drop_down_item, item_list, width):
        # 先创建menu实例,再生成选项
        menu = MDDropdownMenu(caller=drop_down_item, items=[], width_mult=width)
        items_collection = [
            {
                "viewclass": "OneLineListItem",
                "text": item,
                "height": dp(56),
                "on_release": lambda x=item, m=menu: self.Set_DropDown_Item(drop_down_item, m, x),
            } for item in item_list
        ]
        menu.items = items_collection
        return menu

         
    def Set_DropDown_Item(self, drop_down_item, menu, text_item):
        drop_down_item.set_item(text_item)
        menu.dismiss()


class MainApp(MDApp):
    def build(self):
        self.title = 'DROP DOWN ITEM ADDED DYNAMICALLY'
        return View()


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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:07:06