Как я могу отменить выбор ранее выбранной строки в Kivy RecycleView - PullRequest
0 голосов
/ 30 сентября 2018

Мне нужна помощь, чтобы отменить выбор выбранного элемента Label в RecycleView с представлением SelectableLabel.какие-нибудь идеи, как решить это?

я понимаю, что это должно быть написано где-нибудь в '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 голосов
/ 13 июля 2019

Приведенный ниже код выполняет то, что запрашивается, то есть

  1. , включающий только один выбор за один раз, и
  2. , позволяющий отменить выбор выбранного элемента

Он идентичен коду первого ответа, за исключением 3 различий, выделенных ** РАЗНИЦАМИ **.

из приложения импорта kivy.app
из kivy.lang Импорт Builder
из kivy.uix.recycleview импорт RecycleView
из kivy.uix.recycleview.views импорт RecycleDataViewBehavior
из kivy.uix.label импорт Метка
из kivy.properties импорт BooleanProperty
из kivy.uix.recycleboxимпорт RecycleBoxLayout
из kivy.uix.behaviors импорт FocusBehavior
из 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: 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()
0 голосов
/ 30 сентября 2018

FAQ

Хотите иметь возможность многократного выбора строк, а затем отменить выбор отдельной строки?- ikolim Sep 30 '18 в 21:04

не просто выделите одним нажатием и отмените выделение другим нажатием на строке, но также сохраняйте изменение выбора при выборе разных строк.может быть, проще сказать, что я ищу поведение списка в этом повторном обзоре - amihai Sep 30 '18 в 21: 07

Solution

Следующее решение не для multi-select.

Установить выбранное, если строка не выделена, или отменить выделение, если она уже выбрана.

Фрагмент

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'
''')


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

...