如何在Kivy中替换已弃用的ListView?

时间:2020-04-01 15:02:35

标签: python kivy

我现在正在学习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,但未显示,而我可以通过idObjectProperty访问数据。有没有一种比使用ScreenManager,构造类和引用build方法更简单的方式来显示数据?例如类似作者或我的示例但可以正常工作的东西。添加RecycleBoxLayout也不起作用。

2 个答案:

答案 0 :(得分:0)

以奇异果调用您的Recycleview时,请确保它具有适当的ID,然后可以在您的python代码中调用此ID,并应用以下数据:

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

奇异鸟文档站点提供了一个有关如何实现RecycleView的出色示例,请参见:https://kivy.org/doc/stable/api-kivy.uix.recycleview.html

尝试这个基本示例,展示如何将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

答案 1 :(得分:0)

我找到了问题所在。 首先,数据格式必须合适。正如两次摇晃一样,它一定是字典列表。 其次,据我所知,需要显示一些布局。例如,.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'