Kivy: Как создать RecycleView, который работает динамически - PullRequest
0 голосов
/ 11 мая 2019

Я пытаюсь создать свой личный виджет RecycleView. Но результат отображается с некоторыми проблемами.

Результат Result

Неверный результат Wrong result

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.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.clock import Clock

Builder.load_string('''
<SelectableButton>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.9, 0.9, .9, .4) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size

<RV>:
    scroll_type: ['bars', 'content']
    scroll_wheel_distance: dp(100)
    bar_width: dp(10)
    viewclass: 'SelectableButton'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: False
        touch_multiselect: True
''')

nbre = 40
items_1 = ["fruits" + str(i) for i in range(nbre)]
items_2 = ["animaux" + str(i) for i in range(nbre)]
num = range(nbre)

class MyButton(Button):
    """ My Special Button """
    def __init__(self, **kwargs):
        super(MyButton, self).__init__(**kwargs)
        self.position = kwargs.get("position", (None, None))

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            super(MyButton, self).on_touch_down(touch)
            print ("Button {} is pressed on position {}".format(self.text, self.position))
            return False

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


class SelectableButton(RecycleDataViewBehavior, GridLayout):
    ''' Add selection support to the Label '''
    selected = BooleanProperty(False)
    def __init__(self, nbre_cols=None, **kwargs):
        super(SelectableButton, self).__init__(**kwargs)
        self.index = None
        self.cols = nbre_cols
        self.selectable = BooleanProperty(True)

    def add_widget(self, child):
        print ("\tadd_widget {}".format(child.text))
        return super(SelectableButton, self).add_widget(child)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        self.cols = len(data) if not self.cols else self.cols
        for i in range(len(data)):
            self.add_widget(MyButton(text=data['item'+str(i)]['text'], position={'x': i, 'y': index}))

        return super(SelectableButton, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableButton, 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):
        self.selected = is_selected
        if is_selected:
            print("selection changed to line {1} {0}".format(rv.data[index], index))
        else:
            print("selection removed for line {1} {0}".format(rv.data[index], index))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        Clock.schedule_once(self.setData, 1)    

    def setData(self, data=None):
        self.data = [{'item0': {'text': str(n)}, 'item1': {'text': i1}, 'item2': {'text': i2}} for n, i1, i2 in zip(num, items_1, items_2)]


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

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

Цель состоит в том, чтобы иметь возможность динамически отображать некоторые данные. Я посмотрел на некоторые ответы здесь и выбрал некоторую часть кодов, чтобы создать это. В качестве viewclass я использую набор Button. Проблема в том, что код работает нормально. Но когда я прокручиваю вниз и вверх, чтобы увидеть данные. Визуальное начало действовать довольно странно. Это мой код.

...