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

如何通过Python代码向Kivy的Accordion添加AccordionItem?

问题描述

我开发了一个包含Accordion组件的测试应用,希望通过Python代码向Accordion中添加AccordionItem。以下是对应的kv代码和Python代码,但运行Python代码时出现KeyError: 'accordyN'错误,无法找到目标Accordion组件。请问如何通过Python代码向布局中添加kv组件?


kv代码

#:kivy 1.0.9

<LayoutTest>:
    BoxLayout:
        id: mainBox
        orientation: 'horizontal'
        padding: 4
        spacing: 4
        canvas:
            Color:
                rgba: 0, 0.2, 0.4, 1  # Blue-ish color
            Rectangle:
                pos: self.pos
                size: self.size

        # workBox
        BoxLayout:
            orientation: 'vertical'
            canvas:
                Color:
                    rgba: 0.16, 0.11, 0, 1  # brownish color
                Rectangle:
                    pos: self.pos
                    size: self.size

            ListView:
                id: r_list
                orientation: 'vertical'


[AccordionItemTitle@Label]:
    text: '  ' + ctx.title
    halign: 'left'
    valign: 'center'
    text_size: self.size
    normal_background: ctx.item.background_normal if ctx.item.collapse else ctx.item.background_selected
    disabled_background: ctx.item.background_disabled_normal if ctx.item.collapse else ctx.item.background_disabled_selected
    canvas.before:
        Color:
            rgba: self.disabled_color if self.disabled else self.color
        BorderImage:
            source: self.disabled_background if self.disabled else self.normal_background
            pos: self.pos
            size: self.size
        PushMatrix
        Translate:
            xy: self.center_x, self.center_y
        Rotate:
            angle: 90 if ctx.item.orientation == 'horizontal' else 0
            axis: 0, 0, 1
        Translate:
            xy: -self.center_x, -self.center_y
    canvas.after:
        PopMatrix

<ListItem@AccordionItem>:
    title: '2024/12/20  22:00    <reference>'
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'Type 1'
            text_size: self.width, None
        Label:
            text: 'Content 3'
            text_size: self.width, None

<ListView@BoxLayout>:
    Accordion:
        id: accordyN
        orientation: 'vertical'

        AccordionItem:
            title: '2024/12/20  00:00    <reference>'
            BoxLayout:
                orientation: 'vertical'
                size_hint_y: None
                # height: self.minimum_height
                # height: type_label.height + content_label.height
                valign: 'top'
                Label:
                    id: type_label
                    text: 'Type 1'
                    text_size: self.size
                    halign: 'left'
                    valign: 'top'
                Label:
                    id: content_label
                    text: 'Content 1'
                    text_size: self.size
                    halign: 'left'
                    valign: 'top'

        AccordionItem:
            title: '2024/12/20  09:00    <reference>'
            BoxLayout:
                orientation: 'vertical'
                Label:
                    text: 'Type 1'
                    text_size: self.width, self.height
                Label:
                    text: 'Content 2'
                    text_size: self.width, self.height

Python代码

import kivy
from kivy.app import App

# below this kivy version you cannot use the app
kivy.require('1.9.0')

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.accordion import AccordionItem


class LayoutTest(BoxLayout):
    temp = 0


class ListItem(AccordionItem):
    temp = 0


class LayoutTestApp(App):
    mainLayout = None

    def __init__(self, **kwargs):
        super().__init__()

    def build(self):
        self.mainLayout = LayoutTest()
        entry = ListItem(title='2024/12/20  22:00    <reference>')
        self.mainLayout.ids['accordyN'].add_widget(entry)
        return self.mainLayout


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

错误信息

self.mainLayout.ids['accordyN'].add_widget(entry)
'~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'accordyN'


解决方案

错误原因

accordyN这个id属于自定义ListView组件内部的Accordion,而self.mainLayout.ids只能直接访问LayoutTest根布局下的id(也就是mainBox和r_list)。你需要先获取到r_list这个ListView实例,再通过它的ids访问内部的accordyN。

另外注意kv文件开头的#:kivy 1.0.9和Python代码里的kivy.require('1.9.0')版本不一致,建议统一为同一版本(比如改成#:kivy 1.9.0),避免潜在兼容性问题。

修改后的Python代码

import kivy
from kivy.app import App

kivy.require('1.9.0')

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.accordion import AccordionItem


class LayoutTest(BoxLayout):
    temp = 0


class ListItem(AccordionItem):
    temp = 0


class LayoutTestApp(App):
    mainLayout = None

    def __init__(self, **kwargs):
        super().__init__()

    def build(self):
        self.mainLayout = LayoutTest()
        entry = ListItem(title='2024/12/20  22:00    <reference>')
        # 先获取ListView实例r_list,再访问其内部的accordyN
        self.mainLayout.ids['r_list'].ids['accordyN'].add_widget(entry)
        return self.mainLayout


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

额外说明

Kivy的id作用域是当前规则内部:

  • LayoutTest规则里的id(mainBox、r_list)只能通过LayoutTest实例的ids访问
  • 自定义ListView规则里的id(accordyN)只能通过ListView实例的ids访问
    所以必须按照布局层级逐层获取组件,才能找到目标id对应的控件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:00:55