奇异果多选框 [英] Kivy multiple selection with checkboxes

查看:92
本文介绍了奇异果多选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

单击行项目的标签部分有效,但是我注意到单击复选框不会更改选择,我无法解决该选择(我尝试了几种不同的状态绑定,我将它们留了下来在示例代码中被注释掉了)

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

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


编辑:我研究了如何预先选择所有条目,我更新了代码并删除了问题的那一部分.

解决方案

以防万一有人提出我指向正确网址的问题:

您应该考虑使用具有所需所有功能的新RecycleView.在此处查看示例: 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()

I'm using Kivy v1.9.1-dev


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

解决方案

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

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

这篇关于奇异果多选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆