Индекс изменения RecycleView при использовании refresh_from_data () в Kivy - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь создать простую таблицу, в которой при выборе одного элемента в RecycleView выделяется вся строка.Это было решено путем изменения состояния каждой кнопки-переключателя в строке, по которой щелкнули, через ее индекс.Однако, если я хочу вручную добавить некоторые данные в мое повторное представление и затем обновить таблицу с помощью метода refresh_from_data (), это приводит к некоторому странному поведению.Метод refresh_from_data () изменяет индексы кнопок в обзоре корзины.

Изменяя состояние кнопки переключения с индексом = 0, можно наблюдать, как индекс [0] переключается между расположением в верхнем левом углу.угол RecycleView и нижний правый угол RecycleView.Мой код ниже иллюстрирует это.Я установил индекс [0] равным «вниз» при нажатии любой кнопки.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.recycleview.views import RecycleDataViewBehavior


class MyButton(RecycleDataViewBehavior, ToggleButton):
    index = None

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


class TestRecycleView(RecycleView):
    items_per_row = 3
    selected_data = None
    selected_row = None

    def find_row(self, instance):
        rgl = self.ids.gl
        num_buttons = len(rgl.children)
        num_rows = num_buttons // self.items_per_row
        self.selected_row = instance.index // self.items_per_row + 1
        print('Row: ', self.selected_row)
        self.selected_data = self.data[(self.selected_row - 1) * self.items_per_row: self.items_per_row
                                                                                     * self.selected_row]
        print('Data: ', self.selected_data)
        index1 = (num_rows - self.selected_row + 1) * self.items_per_row - 1
        index2 = index1 - self.items_per_row
        state = instance.state
        for index in range(index1, index2, -1):
            rgl.children[index].state = state

        print('======================')
        print('    Add some data     ')
        print('======================')

        # See how index[0] changes between the refresh()
        rgl.children[0].state = "down"
        root = App.get_running_app().root
        root.refresh_from_data()


KV = '''

<MyButton>:
    on_release:
        app.root.find_row(self)

TestRecycleView:
    data: [{'text': str(x)} if x not in range(9,12) else {'text': 'Press here'} for x in range(21)]
    viewclass: 'MyButton'
    id: rv_controller
    target_id: None
    RecycleGridLayout:
        id: gl
        cols: 3
        default_size_hint: 1, None
        orientation: 'vertical'
        key_selection: 'selectable'
        default_size: None, dp(26)
        size_hint_y: None
        height: self.minimum_height
        multiselect: True
        touch_multiselect: True

'''


class Test(App):
    def build(self):
        root = Builder.load_string(KV)
        # root.data = items
        return root


Test().run()

Я пришел к выводу, что индексы переключаются между 0,1,2,3 ...и end, end-1, end-2, ... Это означает, что выбранная строка «зеркально отражается» на среднем ряду между каждым нажатием кнопки.

Но почему RecycleView ведет себя так и что делаетЯ об этом?Все, что я хочу сделать, - это иметь возможность выбрать целую строку одним щелчком мыши, добавить / изменить данные вручную, и я также хочу, чтобы в любой момент времени была выбрана только одна строка.

Но метод refresh_from_data ()делает это очень трудно для меня.

1 Ответ

0 голосов
/ 14 февраля 2019

Я думаю, что немного другой подход будет работать лучше.Вместо того, чтобы устанавливать state определенных кнопок, добавьте свойство state к данным и измените state в данных.Таким образом, RecycleView установит состояние в соответствии с данными, и его замена кнопок не будет иметь значения.Поэтому в kv измените данные на:

TestRecycleView:
    data: [{'text': str(x), 'state': 'normal'} for x in range(21)]

и измените find_row() на:

def find_row(self, instance):
    self.selected_row = instance.index // self.items_per_row + 1
    start_index = (self.selected_row - 1) * self.items_per_row
    for index in range(start_index, start_index + self.items_per_row):
        self.data[index]['state'] = 'down' # change data, not button state
    self.refresh_from_data()
...