带有复选框的 Kivy 多项选择

2022-01-15 00:00:00 python python-2.7 kivy

问题描述

我正在尝试使用 Kivy 创建一个视图,该视图具有默认选中的选项列表,用户可以选择取消选择某些条目(通过单击复选框或行上的任意位置).

I'm trying to create a view using Kivy that has a list of options that are all selected by default, and the user can choose to deselect some entries (by clicking on the checkbox or anywhere on the row).

单击行项目的标签部分有效,但我注意到单击复选框不会更改我无法解决的选择(我尝试了一些不同的状态绑定,我离开了它们在示例代码中注释掉)

Clicking on the label part of the row item works, but I noticed that clicking on the checkbox doesn't change the selection which I can't work out how to solve (I tried a few different state bindings, I left them commented out in the example code)

这是一个简单的例子,展示了我的尝试.

Here is a quick example showing what I've tried.

from kivy.app import App
from kivy.properties import StringProperty, ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.selectableview import SelectableView
from kivy.uix.togglebutton import ToggleButtonBehavior
from kivy.adapters.models import SelectableDataItem
from kivy.lang import Builder

Builder.load_string("""
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import Factory kivy.factory.Factory

<MyListItem>:
    height: 50

    on_state: root.is_selected = args[1] == "down"
    state: "down" if root.is_selected else "normal"

    BoxLayout:
        spacing: 10

        CheckBox:
            on_state: root.is_selected = args[1] == "down"
            state: "down" if root.is_selected else "normal"
            # on_state: root.state = args[1]
            # state: root.state

        Label:
            text: root.name

<Page>:
    orientation: "vertical"

    ListView:
        id: LV
        adapter: ListAdapter(data=root.data, cls=Factory.MyListItem, args_converter=root.args_converter, selection_mode="multiple", propagate_selection_to_data=True)

    Button:
        size_hint_y: None
        text: "print selection"
        on_press: print(LV.adapter.selection)
""")

class MyListItem(ToggleButtonBehavior, SelectableView, BoxLayout):
    name = StringProperty()

    def __repr__(self):
        return "%s(name=%r)" % (type(self).__name__, self.name)

    def on_state(self, me, state):
        print me, state
        if state == "down":
            self.select()
        else:
            self.deselect()
        # self.is_selected = state == "down"

class DataItem(SelectableDataItem):
    def __init__(self, name, **kwargs):
        super(DataItem, self).__init__(**kwargs)
        self.name = name

    def __repr__(self):
        return "%s(name=%r, is_selected=%r)" % (type(self).__name__, self.name, self.is_selected)


class Page(BoxLayout):
    data = ListProperty()

    def __init__(self, **kwargs):
        super(Page, self).__init__(**kwargs)
        self.data = [DataItem("Item {}".format(i), is_selected=True) for i in range(10)]

    def args_converter(self, index, data_item):
        return {
            "index": index,
             "name": data_item.name,
        }


class ExampleApp(App):
    def build(self):
        return Page()


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

我正在使用 Kivy v1.9.1-dev

I'm using Kivy v1.9.1-dev

我想出了如何预先选择所有条目,我已经更新了代码并解决了这部分问题.

I worked out how to get all the entries pre-selected, I've updated the code and took that part of the question out.


解决方案

以防万一别人有问题我指向正确的url:

Just in case someone else has the the question I point to the right url:

您应该考虑新的 RecycleView,它具有您要求的所有功能.在此处查找示例:Kivy:已弃用功能的替代方案

You should consider the new RecycleView, which has all the functionality you request. Look here for a sample: Kivy: alternative to deprecated features

相关文章