在 kivyMD 中选择 MDCheckbox 时出现应用错误
Posted
技术标签:
【中文标题】在 kivyMD 中选择 MDCheckbox 时出现应用错误【英文标题】:App error while selecting a MDCheckbox in kivyMD 【发布时间】:2022-01-14 00:22:44 【问题描述】:我有一个MDList
和MDCheckbox
,我需要选择列表中的一些项目,但例如当我选择第一个项目时,最后一个项目也被选中,当我选择第二个项目时,倒数第二个项目也被选中,反之亦然,如果我选择最后一个元素,那么第一个元素也会被选中。这只发生在列表的第一个和最后两个元素上,当我在它们之间选择一个元素时,它可以正常工作。我怎样才能防止这种情况发生?
这是我的代码的类似示例:
from kivymd.uix.dialog import MDDialog
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.snackbar import Snackbar
from kivy.properties import ObjectProperty
from kivymd.uix.list import ILeftBodyTouch, ThreeLineListItem, ThreeLineAvatarIconListItem
from kivy.uix.recycleview import RecycleView
from kivymd.uix.selectioncontrol import MDCheckbox
from functools import partial
KV='''
WindowManager:
#LoginWindow:
MainWindow:
SecondWindow:
<ListItemWithCheckbox>:
LeftCheckbox:
<MainWindow>
name: 'main'
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'test'
MDBoxLayout:
orientation:'vertical'
spacing: dp(10)
padding: dp(20)
RecycleView:
id: rv
key_viewclass: 'viewclass'
key_size: 'height'
bar_width: dp(10)
RecycleBoxLayout:
padding: dp(10)
default_size: None, dp(80)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
'''
product_dict='name 1': (1, 2),
'name 2': (3,4),
'name 3':(4,2),
'name 4':(4,2),
'name 5':(4,2),
'name 6':(4,2),
'name 7':(4,2),
'name 8':(4,2),
'name 9':(4,2) ,
'name 10':(4,2)
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class ListItemWithCheckbox(ThreeLineAvatarIconListItem):
pass
class LeftCheckbox(ILeftBodyTouch, MDCheckbox):
pass
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style="Dark"
self.theme_cls.primary_palette="Green"
return Builder.load_string(KV)
def on_start(self):
self.set_list()
def set_list(self):
self.root.get_screen('main').ids.rv.data = []
for key in product_dict:
self.root.get_screen('main').ids.rv.data.append(
"viewclass": "ListItemWithCheckbox",
"text": key,
"secondary_text": f'Item 1: product_dict[key][0]',
"tertiary_text": f'Item 2: product_dict[key][1]',
"on_press": partial(self.action, key)
)
def action(self, instance):
print(instance)
MainApp().run()
【问题讨论】:
【参考方案1】:因为RecycleView
回收viewclass
,所以在viewclass
中设置的属性将反映在viewclass
的回收实例中,除非您明确处理这些属性。因此,如果您的ListItemWithCheckbox
中的LeftCheckbox
的state
在一个实例中设置为down
,则当该实例被回收以显示data
中的另一个项目时,它将保持为down
。
解决方法是在您的data
中处理LeftCheckbox
的state
。为此,您需要能够确定data
的哪个项目当前与LeftCheckbox
相关联。
一种方法是向ListItemWithCheckbox
添加属性:
class ListItemWithCheckbox(ThreeLineAvatarIconListItem):
selected = BooleanProperty(False) # is this checkbox down
data_index = NumericProperty(-1) # index into the RV data
def state_changed(self):
self.selected = self.ids.lcb.state == 'down' # set the selected property
# save the change to the data
rv = MDApp.get_running_app().root.get_screen('main').ids.rv
rv.data[self.data_index]['selected'] = self.selected
然后调整set_list()
方法初始化新属性:
def set_list(self):
self.root.get_screen('main').ids.rv.data = []
index = 0
for key in product_dict:
self.root.get_screen('main').ids.rv.data.append(
"viewclass": "ListItemWithCheckbox",
"text": key,
"secondary_text": f'Item 1: product_dict[key][0]',
"tertiary_text": f'Item 2: product_dict[key][1]',
"on_press": partial(self.action, key),
"selected": False,
"data_index": index
)
index += 1
并在kv
修改ListItemWithCheckbox
:
<ListItemWithCheckbox>:
LeftCheckbox:
id: lcb
on_press: root.state_changed() # save change to the data
state: 'down' if root.selected else 'normal' # get state from the "selected" property
【讨论】:
以上是关于在 kivyMD 中选择 MDCheckbox 时出现应用错误的主要内容,如果未能解决你的问题,请参考以下文章