Kivy的RecycleView是否可以作为ListView的替代品?它是如何工作的?

12

我应该先说明一下,我对Kivy还是一个新手。 我试图查找类似的问题,但它们要么过时了,要么不清楚。

我正在寻找一种显示元素列表的东西,其中用户可以选择一个来与其他小部件(如按钮等)交互。 我偶然发现了ListView文档页,但它明确指出ListView已被弃用,必须改用RecycleView

现在的问题是,文档似乎不太清楚(至少对我来说),关于如何使用RecycleView。它肯定比其他小部件更复杂,而我似乎无法理解它。

为了更好地分解成易于消化的问题: 1.如何定义充当项列表的RecycleView? 2.我如何为其提供项目? 3.我如何与之交互,特别是使仅一个项目可选择,在选择某些内容并自动在事件上选择某些内容时检测到?

哦,顺便说一句,我更喜欢尽可能使用kv语言。

我非常感谢在找到或理解文档资源方面提供帮助,以便将来能更普遍地理解这一点。我真的希望有关于这些复杂功能的教程,但如果存在,那么很难找到。

2个回答

6
下面的示例演示了如何使用Recycleview显示按钮列表,并在选择每个按钮时显示弹出窗口。

示例

main.py

from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from kivy.properties import ListProperty, StringProperty, ObjectProperty


class MessageBox(Popup):

    def popup_dismiss(self):
        self.dismiss()


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
    """ Adds selection and focus behaviour to the view. """
    selected_value = StringProperty('')
    btn_info = ListProperty(['Button 0 Text', 'Button 1 Text', 'Button 2 Text'])


class SelectableButton(RecycleDataViewBehavior, Button):
    """ Add selection support to the Label """
    index = None

    def refresh_view_attrs(self, rv, index, data):
        """ Catch and handle the view changes """
        self.index = index
        return super(SelectableButton, self).refresh_view_attrs(rv, index, data)

    def on_press(self):
        self.parent.selected_value = 'Selected: {}'.format(self.parent.btn_info[int(self.id)])

    def on_release(self):
        MessageBox().open()


class RV(RecycleView):
    rv_layout = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x), 'id': str(x)} for x in range(3)]


class TestApp(App):
    title = "RecycleView Button Popup Demo"

    def build(self):
        return RV()


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

test.kv

#:kivy 1.10.0

<MessageBox>:
    title: 'Popup Message Box'
    size_hint: None, None
    size: 400, 400

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: app.root.rv_layout.selected_value
        Button:
            size_hint: 1, 0.2
            text: 'OK'
            on_press:
                root.dismiss()

<SelectableButton>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (0.0, 0.9, 0.1, 0.3)
        Rectangle:
            pos: self.pos
            size: self.size

<RV>:
    rv_layout: layout
    viewclass: 'SelectableButton'
    SelectableRecycleBoxLayout:
        id: layout
        default_size: None, dp(56)
        default_size_hint: 0.1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: "vertical"

输出

具有弹出窗口的按钮的Recycleview


2
我很感激你的答复。显然,我仍然缺乏对一些基本概念的理解,以完全掌握你代码的每个部分,但我会认真学习它。谢谢。 - theberzi

2

我做了一个更简单的例子。在我的示例中,可以使用kv语言中RecycleViewRow类中的小部件更改每行的布局。我已经在每一行中放置了一个标签和一个按钮作为示例。希望这能更有帮助。

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.popup import Popup

Builder.load_string('''
#:kivy 1.10.0
#: import Popup kivy.uix.popup

<MessageBox>:
    title: 'Popup Message Box'
    size_hint: None, None
    size: 400, 400

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: root.message
        Button:
            size_hint: 1, 0.2
            text: 'OK'
            on_press: root.dismiss()

<RecycleViewRow>:
    orientation: 'horizontal'
    Label:
        text: root.text
    Button:
        text: 'Show'
        on_press: app.root.message_box(root.text)

<MainScreen>:
    viewclass: 'RecycleViewRow'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'                    
                    ''')

class MessageBox(Popup):
    message = StringProperty()

class RecycleViewRow(BoxLayout):
    text = StringProperty()   

class MainScreen(RecycleView):    
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x), 'id': str(x)} for x in range(3)]

    def message_box(self, message):
        p = MessageBox()
        p.message = message
        p.open() 
        print('test press: ', message)

class TestApp(App):
    title = "RecycleView Direct Test"

    def build(self):
        return MainScreen()

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

你在哪里定义RecycleBoxLayout - shamilpython
@shamilpython,你不需要定义它,它已经在kivy.uix.recycleboxlayout模块中定义了,但是使用的小部件是在RecycleViewRow类中定义的。 - Randolfo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接