如何正确编辑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
相关产品推荐
相关产品推荐

