如何在kivy中替换不推荐的ListView?

2024-05-31 23:35:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我现在正在学习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"]

还有,派克

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也不起作用


Tags: textappsizebutton作者listviewusmx
2条回答

在kivy中调用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

kivy docs站点有一个关于如何实现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

我发现了这个问题。 首先,数据的格式必须合适。正如twicejiggled所显示的,这一定是一个目录列表。 其次,据我所知,需要一些布局来展示。例如,以.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'

相关问题 更多 >