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

如何正确编辑KivyMD列表的指定条目并放回原位置?

问题核心原因

现有代码逻辑的问题出在三个地方:

  • 点击列表项触发删除时,没有记录被删除项原本在protocol列表和MDList控件中的位置,编辑完成后只能默认往列表末尾追加
  • 编辑非末尾条目时,错误使用了全局自增的rod、dist变量计算条目属性,这两个变量只应该在新增条目时自增,编辑旧条目时要保留原有的Rod、Distance值,不能用当前的全局变量值
  • 列表项绑定的点击事件只传了Proc、Depth两个字段和控件实例,没有把条目对应的Rod、Distance、原始索引一起传入,回填和更新时拿不到完整的原始数据
修复步骤
  • 新增类变量editing_index = None,专门用来存储当前处于编辑状态的条目的原始索引
  • 修改列表项的点击回调参数,把条目完整的Rod、Distance、Proc、Depth值和对应索引全部传入,点击删除时把索引存到editing_index里
  • 重写edit_entry逻辑:提交编辑时不要往列表末尾追加,直接把修改后的数据插回editing_index对应的位置,UI控件也插入到对应索引位置,全程不修改全局的rod、dist计数,操作完成后把editing_index重置为None,恢复按钮状态
修复后完整代码
import re

from kivy.lang import Builder
from kivy.uix.button import Button

from kivymd.app import MDApp
from kivymd.uix.list import OneLineListItem

KV = '''
BoxLayout:
    GridLayout:
        cols:3
        GridLayout:
            id: testing
            cols:2
            MDLabel:
                text: '%:'
            TextInput:
                id: proc
                multiline: False
                input_type: 'number'
                input_filter: 'int'
        GridLayout:
            cols:2
            MDLabel:
                text: 'Depth:'
            TextInput:
                id: depth
                multiline: False
                input_type: 'number'
                input_filter: 'int'
        Button:
            id: add
            text: 'Add'
            on_release:
                app.add_entry(proc.text, depth.text)
                proc.text = ''
                depth.text = ''
        Button:
            id: edit
            text: 'Edit'
            disabled: True
            on_release:
                app.edit_entry(proc.text, depth.text)
                proc.text = ''
                depth.text = '' 
    ScrollView:
        size_hint: .5, .5
        MDList:
            id: container
'''


class Test(MDApp):
    rod = 1
    dist = 3
    protocol = list()  # {Rod:_,Distance:_,Proc:_,Depth:_}
    editing_index = None  # 记录正在编辑的条目原始索引

    def edit_entry(self, proc, depth):
        # 取出被编辑条目的原始Rod、Distance值,不使用全局自增变量
        origin_rod = self.protocol[self.editing_index]["Rod"]
        origin_dist = self.protocol[self.editing_index]["Distance"]
        # 更新对应索引位置的数据
        self.protocol[self.editing_index] = {"Rod": origin_rod, "Distance": origin_dist, "Proc": proc, "Depth": depth}
        clean_entry = re.sub(r"[,'{}]", '', str(self.protocol[self.editing_index]))
        new_entry = OneLineListItem(
            text=clean_entry,
            on_press=lambda x, r=origin_rod, d=origin_dist, p=proc, dep=depth, idx=self.editing_index: 
            self.change_entry(p, dep, new_entry, r, d, idx)
        )
        # 把控件插回原来的索引位置,而非列表末尾
        self.root.ids.container.add_widget(new_entry, index=self.editing_index)
        # 重置编辑状态
        self.editing_index = None
        self.root.ids.edit.disabled = True
        self.root.ids.add.disabled = False

    def change_entry(self, proc, depth, entry, rod, dist, index):
        # 回填输入框
        self.root.ids.proc.text = proc
        self.root.ids.depth.text = depth
        # 记录当前编辑的条目索引
        self.editing_index = index
        # 删除选中条目
        self.root.ids.container.remove_widget(entry)
        # 切换按钮状态
        self.root.ids.edit.disabled = False
        self.root.ids.add.disabled = True


    def add_entry(self, proc, depth):
        current_index = len(self.protocol)
        entry_data = {"Rod": self.rod, "Distance": self.dist, "Proc": proc, "Depth": depth}
        self.protocol.append(entry_data)
        clean_entry = re.sub(r"[,'{}]", '', str(entry_data))
        entry = OneLineListItem(
            text=f"{clean_entry}", 
            on_press=lambda x, r=self.rod, d=self.dist, p=proc, dep=depth, idx=current_index: 
            self.change_entry(p, dep, entry, r, d, idx)
        )
        self.root.ids.container.add_widget(entry)
        # 只有新增条目时才自增rod和dist
        self.rod += 1
        self.dist += 3

    def build(self):
        return Builder.load_string(KV)


Test().run()
print(Test.protocol)
效果说明

修复后不管编辑哪个位置的条目,都会保留原有的Rod、Distance序号,修改完直接插回原来的位置,不会打乱整体列表顺序,全局的rod、dist计数只会在新增条目时变化,不会因为编辑操作出现计数混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:12:19