我如何在kivy recycleview中取消选择先前选择的行

时间:2018-09-30 08:50:05

标签: python kivy kivy-language

我需要帮助,在带有SelectableLabel视图的RecycleView中取消选择选定的标签项。 任何想法如何解决?

我知道它应该写在“ def apply_selection”中的某个位置,但是我无法使其正常工作

示例:

example

我希望能够对所选行进行另一次单击,然后将所选内容删除。

我认为用于此的代码应该在此处:

    def apply_selection(self, rv, index, is_selected):
    ''' Respond to the selection of items in the view. '''
        self.selected = is_selected

我尝试使用第三个输入来指定当前选择,但实际上没有用。 1.此方法是我需要修改以实现之后即时消息的地方吗? 2.如果是这样,有什么想法如何正确地做到这一点?

2 个答案:

答案 0 :(得分:0)

如果未选择行,则设置为选中状态;如果已选择行,则取消选择。

摘要

def apply_selection(self, rv, index, is_selected):
    ''' Respond to the selection of items in the view. '''
    self.selected = not self.selected

示例

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

Builder.load_string('''
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: True
        touch_multiselect: True
''')


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = not self.selected


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]


class TestApp(App):
    def build(self):
        return RV()


if __name__ == '__main__':
    TestApp().run()

输出

Img01 - Selected Label 2 Img02 - Clicked on Label 8 & Label 2 auto deselected

答案 1 :(得分:0)

下面的代码执行要求的操作,即

  1. 一次仅启用一个选择,并且
  2. 允许取消选择所选项目

与第一个答案的代码相同,除了3个差异用突出显示 **差异**。

  

从kivy.app导入应用程序
  从kivy.lang导入生成器
  从   kivy.uix.recycleview导入RecycleView
  从   kivy.uix.recycleview.views导入RecycleDataViewBehavior
  从   kivy.uix.label导入标签
  从kivy.properties导入   BooleanProperty
  从kivy.uix.recycleboxlayout导入   RecycleBoxLayout
  从kivy.uix.behaviors导入FocusBehavior
  从   kivy.uix.recycleview.layout导入LayoutSelectionBehavior

Builder.load_string('''
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: False # ** DIFFERENCE **
        touch_multiselect: False # ** DIFFERENCE **
''')


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''

    # required to authorise unselecting a selected item
    touch_deselect_last = BooleanProperty(True) # ** DIFFERENCE **


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = not self.selected


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]


class RVMainApp(App):
    def build(self):
        return RV()


if __name__ == '__main__':
    RVMainApp().run()