Как заменить устаревший ListView в киве? - PullRequest
0 голосов
/ 01 апреля 2020

Я сейчас изучаю kivy и читаю Создание приложений с помощью kivy. Автор использует следующий код:

.kv

AddLocationForm:

<AddLocationForm@BoxLayout>:
    orientation : 'vertical'
    BoxLayout:
        pos : 100, 100
        height : '40dp'
        size_hint_y : None

        TextInput:
            size_hint_x : 50
        Button:
            text : 'search'
            size_hint_x : 25
        Button:
            text : 'current location'
            size_hint_x : 25
    ListView:
        item_strings: ["Palo Alto, MX", "Palo Alto, US"]

и .py

from kivy.app import App


class FirstKivyApp(App):
    pass



FApp = FirstKivyApp()
FApp.run()

Но, насколько я понимаю, ListView устарел. Предполагается, что он будет изменен в RecycleView сейчас. Я проверил некоторые решения, но они не имеют смысла для меня, потому что используют вещи, которые я еще не достиг. Я пытался использовать

RecycleView:
    data : ["Palo Alto, MX", "Palo Alto, US"]

вместо ListView, но он не отображается, тогда как я могу получить доступ к данным через id и ObjectProperty. Есть ли способ отобразить данные более простым способом, чем использование ScreenManager, создание классов и обращение к методу build? Например, что-то вроде автора или моего примера, но работает. Добавление RecycleBoxLayout тоже не сработало.

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Я выяснил проблему. Во-первых, формат данных должен быть подходящим. Как дважды показал, это должен быть список диктов. Во-вторых, насколько я понял, для показа нужна какая-то раскладка. Например, этот код в .kv будет работать:

RecycleView:
    data : [{'text':'text'} for x in range(50)]
    viewclass: 'Label'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
0 голосов
/ 01 апреля 2020

При вызове вашего Recycleview в kivy убедитесь, что у него есть соответствующий идентификатор, после чего его можно вызвать в коде python с данными, указанными со следующим:

rows = ["Palo Alto, MX", "Palo Alto, US"]  # declare list
self.ids.rv.data = [{'text':str(row)}for row in rows]  # add list

На сайте kivy docs есть отличный пример того, как реализовать RecycleView, найденный здесь: https://kivy.org/doc/stable/api-kivy.uix.recycleview.html

Попробуйте это для базового c примера, показывающего, как использовать ScreenManager с RecycleView:

import kivy
# import main libraries, import object types and layouts
from kivy.config import Config
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.properties import (StringProperty, ObjectProperty, 
OptionProperty, NumericProperty, ListProperty, BooleanProperty)
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.behaviors import FocusBehavior
# import screen features
from kivy.uix.label import Label
from kivy.uix.button import Button

# load in kv file, deals with cosmetics of each screen
kv = """
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if root.selected else (0, 0, 0, .1)
        Rectangle:
            pos: self.pos
            size: self.size 
<SelectScreen>:
    BoxLayout:
        canvas:
            Color:
                rgba: 0.3, 0.3, 0.3, 1
            Rectangle:
                size: self.size
        orientation: 'vertical'
        GridLayout:
            cols: 2
            rows: 1
            size_hint_y: .25
            height: dp(54)
            padding: dp(8)
            spacing: dp(16)
            Button:
                text: 'Select all'
                font_size: 24
                on_release:
                    controller.select_all(len(rv.data))
            Button:
                text: 'Deselect all'
                font_size: 24
                on_release:
                    controller.clear_all()  
        RecycleView:
            id: rv
            scroll_type: ['bars', 'content']
            scroll_wheel_distance: dp(114)
            bar_width: dp(10)
            viewclass: 'SelectableLabel'
            SelectableRecycleBoxLayout:
                id: controller
                key_selection: 'selectable'
                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
                spacing: dp(2)
"""
Builder.load_string(kv)

# Adds selectable labels to lists (recycleview)
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''

    def get_nodes(self):
        nodes = self.get_selectable_nodes()
        if self.nodes_order_reversed:
            nodes = nodes[::-1]
        if not nodes:
            return None, None

        selected = self.selected_nodes
        if not selected:  # nothing selected, select the first
            self.select_node(nodes[0])
            return None, None

        if len(nodes) == 1:  # the only selectable node is selected already
            return None, None

        last = nodes.index(selected[-1])
        self.clear_selection()
        return last, nodes

    def select_all(self, num):
        print(num)
        #print(len(self.ids.rv.data))
        last, nodes = self.get_nodes()
        print(nodes)
        for x in range(num):
            print(x)
            self.select_node(x)

    def clear_all(self):
        self.clear_selection()

# Create action on selectable list, for example apply selection remembers previous selection and saves to sqlite db
class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)
    index = int

    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 = is_selected
        if self.selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))

# Screen for selecting from recycleview         
class SelectScreen(Screen):
    interfacename = StringProperty()

    def __init__(self, **kwargs):   
        super(SelectScreen, self).__init__(**kwargs)
        rows = ["Palo Alto, MX", "Palo Alto, US"]  # declare list
        self.ids.rv.data = [{'text':str(row)}for row in rows]  # add list

    def select(self): # selects participants from list new value to database
        print (self.ids.rv.data[val[0]]['text'])

    def selectall(self):
        for num in range(len(self.ids.rv.data)):
            SelectableLabel.apply_selection(self, self.ids.rv, num, True)   

# screen manager
sm = ScreenManager()
sm.add_widget(SelectScreen(name='select')) # main starting menu

# Build the app return screenmanager
class RecycleviewApp(App):
    def build(self):
        return sm

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

Пример изображения приложения и приложения печати терминала и удаления выбора RecycleView:

enter image description here

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