Kivy RecycleView для создания таблицы, содержащей много данных. Как ускорить процесс? - PullRequest
0 голосов
/ 18 апреля 2020

Я создаю прокручиваемую таблицу в python киве, используя RecycleView. Таблица должна содержать почти 1100 строк и 10 столбцов ... RecycleView выполняет отложенную загрузку ... Реально слишком медленно.

Кто-нибудь знает, как ускорить процесс? Может быть, RecycleView не подходит?

спасибо!

      BoxLayout:
            RecycleView:
                viewclass: 'background_example'
                data: [{'text': str(x)} for x in range(10000]
                RecycleGridLayout:
                    cols: 10
                    size_hint: 1, None
                    default_size: None, dp(20)
                    default_size_hint: 1, None
                    height: self.minimum_height
                    width: self.minimum_width

Ответы [ 3 ]

1 голос
/ 18 апреля 2020

Я вижу две проблемы с вашим кодом:

  1. Вы создаете этот большой список из 10000 элементов дважды. Один раз в методе on_pre_enter() для Screen_2 и снова в коде kv для Screen_2
  2. Вы создаете этот большой список в главном потоке, который замораживает ваш GUI.

Для решения первой проблемы вы можете изменить kv на Screen_2:

<Screen_2>:
    BoxLayout:
        RecycleView:
            viewclass: 'Sfondo_tabella'
            # data: [{'text': str(x)} for x in root.data_items]
            data: root.data_items  # just reference the list instead of recreating it
            RecycleGridLayout:
                cols: 10
                size_hint: 1, None
                default_size: None, dp(20)
                default_size_hint: 1, None
                height: self.minimum_height
                width: self.minimum_width

Чтобы решить вторую проблему, используйте Thread для создания данных в Screen_2:

class Screen_2(Screen):
    data_items = ListProperty([])

    def on_pre_enter(self, *args):
        # start the thread
        Thread(target=self.build_data).start()

    def build_data(self):
        x = 0
        # break the data build into 20 pieces
        for i in range(20):
            tmp_data = []
            for j in range(500):
                # create data entry for the current x and save it in tmp_data
                tmp_data.append({'text': str(x)})
                x += 1
            # add this block of data to the data_items on the main thread
            Clock.schedule_once(partial(self.load_data, tmp_data))

    def load_data(self, tmp_data, dt):
        self.data_items.extend(tmp_data)
0 голосов
/ 21 апреля 2020

Я протестировал ваше решение и работает очень хорошо. спасибо ..

Еще один вопрос:

Для реализации вашего решения в реальном случае, если нам нужно импортировать данные из таблицы, используя postgres, не зная, сколько элементов мне нужно создать Как адаптировать код? (при условии, что таблица содержит 1000 строк и 10 столбцов)

Я только отредактировал функцию 'build_data', получив 10-кратное ускорение выполнения кода (с 50 se c до 5 se c) , но это все еще намного медленнее, чем код, который вы опубликовали (1,5 se c), я думаю, потому что я разбиваю сборку данных на 1000 частей (строк), а не на 20 ...

    def build_data(self):
        self.data_items = ''

        stato_maschere = psycopg2.connect(dsn)
        cur = stato_maschere.cursor()

        cur.execute("SELECT col_1, col_2, col_3, col_4, col_5, col_6, col_7, col_8, col_9, col_10 "
                    "FROM table_1 "
                    "WHEREcol_1 != '' ")

        rows = cur.fetchall()

        for row in rows:
            tmp_data = []
            for x in row:
                tmp_data.append({'text': str(x)})
            Clock.schedule_once(partial(self.load_data, tmp_data))
0 голосов
/ 18 апреля 2020

Вот минимальный воспроизводимый пример:

Пока у нас не будет только 1000 ячеек, таблица будет создана за 2 или 3 секунды.

Если вместо 1000 я пишу 10.000 в for l oop, моему p c понадобится около 50 секунд, чтобы создать таблицу, состоящую из 10.000 ячеек .. это недопустимо.

temp.py:

from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.properties import ListProperty

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

class Screen_1(Screen):
    pass

class Screen_2(Screen):
    data_items = ListProperty([])
    def on_pre_enter(self, *args):
        for x in range(1000):
            self.data_items.append(x)

class TempApp(App):
    pass

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

temp.kv:

ScreenManager:
    id: screen_manager
    name: "screen_manager"

    Screen_1:
        id: screen_1
        name: "Screen_1"
        manager: screen_manager

    Screen_2:
        id: screen_2
        name: "Screen_2"
        manager: screen_manager

<Sfondo_tabella>:
    # Draw a background to indicate selection
    color: 0,0,0,1
    font_size:  self.height * 0.5
    text_size: self.width, None
    valign: 'top'
    halign: 'center'

    canvas.before:
        Color:
            rgba: (1, 1, 1, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    canvas:
        Color:
            rgba:0,0,0,1
        Line:
            width:0.5
            rectangle:(self.x,self.y,self.width,self.height)


<Screen_1>:
    Button:
        text: "Create table"
        on_press:
            root.manager.transition.direction = 'up'
            root.manager.current = 'Screen_2'

<Screen_2>:

    BoxLayout:
        RecycleView:
            viewclass: 'Sfondo_tabella'
            data: [{'text': str(x)} for x in root.data_items]
            RecycleGridLayout:
                cols: 10
                size_hint: 1, None
                default_size: None, dp(20)
                default_size_hint: 1, None
                height: self.minimum_height
                width: self.minimum_width

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...