Kivy多选旋转选择器小部件

4
我正在寻找一个kivy小部件(最好是Python + kv文件),类型为spinner(或类似物),我可以通过复选框选择多个项目。所选项目应在元组中可用。(原文有问号,不确定是否需要翻译)
在图片start.png中,您将找到起始情况。

enter image description here

在一个表单中,有一个标签和一个文本输入字段。点击时,应弹出可用选项列表。为此,我使用了一个Spinner小部件。请参见图片select.png。

enter image description here

我希望从这个列表中选择多个项目。在“荷兰语”旁边的示例中,我已经选择了“英语”。

完成后,文本输入字段应显示所选项目的逗号分隔列表。请参见图片result.png。

enter image description here

我已经尝试使用多选模式在ListView中实现此功能。但是ListView绑定在TextField区域。 我尝试将ListView放在弹出窗口中。但由于某种原因,这也无法实现.... 非常感谢您提供任何建议。 提前致谢。

我不完全清楚你想要什么,但我认为这样的小部件并不存在。相反,将其他基本小部件组合起来以获得所需的结果应该很容易。 - inclement
我能理解。我的教学技巧并不是很好......所以我编辑了问题并添加了一些图片。希望这样更清楚明白。 - Bill Bridge
请添加您所看到的确切错误,只有通过具体说明,您才能获得所需的帮助。 - user1544500
2个回答

12

Kivy 默认情况下没有这样的小部件,但使用 Button+DropDown+ToggleButton 很容易创建自定义小部件。

from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.properties import ListProperty, ObjectProperty
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button

class MultiSelectSpinner(Button):
    """Widget allowing to select multiple text options."""

    dropdown = ObjectProperty(None)
    """(internal) DropDown used with MultiSelectSpinner."""

    values = ListProperty([])
    """Values to choose from."""

    selected_values = ListProperty([])
    """List of values selected by the user."""

    def __init__(self, **kwargs):
        self.bind(dropdown=self.update_dropdown)
        self.bind(values=self.update_dropdown)
        super(MultiSelectSpinner, self).__init__(**kwargs)
        self.bind(on_release=self.toggle_dropdown)

    def toggle_dropdown(self, *args):
        if self.dropdown.parent:
            self.dropdown.dismiss()
        else:
            self.dropdown.open(self)

    def update_dropdown(self, *args):
        if not self.dropdown:
            self.dropdown = DropDown()
        values = self.values
        if values:
            if self.dropdown.children:
                self.dropdown.clear_widgets()
            for value in values:
                b = Factory.MultiSelectOption(text=value)
                b.bind(state=self.select_value)
                self.dropdown.add_widget(b)

    def select_value(self, instance, value):
        if value == 'down':
            if instance.text not in self.selected_values:
                self.selected_values.append(instance.text)
        else:
            if instance.text in self.selected_values:
                self.selected_values.remove(instance.text)

    def on_selected_values(self, instance, value):
        if value:
            self.text = ', '.join(value)
        else:
            self.text = ''


kv = '''
BoxLayout:
    orientation: 'vertical'

    BoxLayout:

        Label:
            text: 'Select city'

        MultiSelectSpinner:
            id: city
            values: 'Sydney', 'Moscow', 'Warsaw', 'New York', 'Tokio'

    BoxLayout:

        Label:
            text: 'Select your favorite food'

        MultiSelectSpinner:
            id: food
            values: 'Fish and chips', 'Hot-dog', 'Hamburger'

    Label:
        text: 'You selected {} cities and {} as your favourite food.'.format(city.text, food.text)

<MultiSelectOption@ToggleButton>:
    size_hint: 1, None
    height: '48dp'

'''

runTouchApp(Builder.load_string(kv))

嗨,Rafalo,这正是我在寻找的。同时,学习如何组合kivy小部件也非常好(我是Kivy的初学者)。非常感谢您的时间和分享经验。 - Bill Bridge

1
我得到了解决方案.. 这是路径:在kv文件中,首先我们可以提到下拉小部件,在下拉菜单下面,我们将提到复选框,这就是答案.. 这是kv文件代码:
DropDown:
                    padding: 0, 0, 0, root.width * 0.4
                    id: dropdown
                    on_select: btn.text = '{}'.format(args[1])

                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: person
                            text: 'Person'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(person.text, self.active)
                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: vehicle
                            text: 'Vehicle'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            id: vecle
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(vehicle.text, self.active)
                    GridLayout:
                        size_hint_y: None
                        height: 44
                        cols: 2
                        row_default_height: '10dp'
                        Label:
                            id: aircraft
                            text: 'Air_craft'
                            text_size: self.size
                            valign: 'middle'
                        CheckBox:
                            text: 'check me'
                            on_active:
                                root.on_checkbox_active(aircraft.text, self.active)

这是 .py 文件:

class My_class(BoxLayout):

def on_checkbox_active(checkbox_ref, name, checkbox_value):
    if checkbox_value:
        print('', name, 'is active')
    else:
        print('', name, 'is inactive')
pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接