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

使用KivyMD遇AttributeError:无法通过ID访问Tab内组件

问题解决方案

核心错误原因

你报错的根源是错误引用了tab_box的位置:tab_box是属于当前切换到的<Tab>实例的组件,而非self.root的子组件,所以self.root.ids.tab_box会找不到对应的ID。同时还要避免重复添加卡片,每次切换Tab时需要先清空容器。


分步修正代码

1. 修正Tab内组件引用逻辑

修改on_tab_switch函数,使用回调参数里的instance_tab(当前激活的Tab实例)来获取tab_box,同时添加清空逻辑:

def on_tab_switch(
        self, instance_tabs, instance_tab, instance_tab_label, tab_text
):
    if tab_text == "section name":
        # 先清空容器,防止重复添加卡片
        instance_tab.ids.tab_box.clear_widgets()
        newss = ["news1", "news2", "news3", "news4", "news5"]
        for news in newss:
            card = CustomMD3Card(text=news)
            # 绑定卡片点击跳转事件
            card.bind(on_release=lambda x, news=news: self.open_news_detail(news))
            instance_tab.ids.tab_box.add_widget(card)

# 新增新闻详情跳转函数
def open_news_detail(self, news_title):
    # 这里替换为你的实际跳转逻辑,比如打开详情页、弹窗等
    print(f"打开新闻:{news_title}")

2. 给MD3Card添加text属性

默认MD3Card没有text属性,需要在Python中自定义卡片类并添加属性绑定:

from kivy.properties import StringProperty
from kivymd.uix.card import MD3Card

class CustomMD3Card(MD3Card):
    text = StringProperty("")

同时修改KV代码中的卡片定义:

<CustomMD3Card>
    padding: 4
    size_hint: None, None
    size: "200dp", "100dp"
    MDLabel:
        id: card_label
        text: root.text
        adaptive_size: True
        color: "grey"
        pos: "12dp", "12dp"
        bold: True

3. 确保Tab类正确定义

需要在Python中对应KV里的<Tab>类:

from kivymd.uix.screen import MDScreen

class Tab(MDScreen):
    pass

完整代码示例

Python部分

from kivy.properties import StringProperty
from kivymd.app import MDApp
from kivymd.uix.card import MD3Card
from kivymd.uix.screen import MDScreen

class Tab(MDScreen):
    pass

class CustomMD3Card(MD3Card):
    text = StringProperty("")

class NewsApp(MDApp):
    def build(self):
        return self.root

    def on_tab_switch(
            self, instance_tabs, instance_tab, instance_tab_label, tab_text
    ):
        if tab_text == "section name":
            instance_tab.ids.tab_box.clear_widgets()
            newss = ["news1", "news2", "news3", "news4", "news5"]
            for news in newss:
                card = CustomMD3Card(text=news)
                card.bind(on_release=lambda x, news=news: self.open_news_detail(news))
                instance_tab.ids.tab_box.add_widget(card)

    def open_news_detail(self, news_title):
        # 替换为你的实际跳转逻辑
        print(f"查看新闻详情:{news_title}")

if __name__ == "__main__":
    NewsApp().run()

KV部分

<Tab>
    ScrollView:
        MDBoxLayout:
            id: tab_box
            orientation: "vertical"      
            adaptive_size: True
            spacing: "56dp"
            pos_hint: {"center_x": .5, "center_y": .5}   

<CustomMD3Card>
    padding: 4
    size_hint: None, None
    size: "200dp", "100dp"
    MDLabel:
        id: card_label
        text: root.text
        adaptive_size: True
        color: "grey"
        pos: "12dp", "12dp"
        bold: True

# 主界面(包含MDTabs和Tab实例)
Screen:
    MDTabs:
        id: tabs
        on_tab_switch: app.on_tab_switch(*args)
        Tab:
            text: "section name"
        Tab:
            text: "其他栏目"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:55:45