【问题标题】:RecycleView Module in KivyKivy 中的 RecycleView 模块
【发布时间】:2018-01-16 17:55:37
【问题描述】:

新成员,第一次发帖。我会尽量具体和明确。以下代码取自 kivy 的关于RecycleView module 的网页。我想使用这段代码,但是,我不想使用 KV lang 和 Builder,而是用纯 Python 3 编写代码。我尝试将 RecycleBoxLayout 类添加为小部件是完全失败的,因为结果只是一个黑色的窗口。只有添加“视图类”才有效。显然,这里有一些我不理解或遗漏的东西。我还附上了我重写代码的尝试。

任何帮助将不胜感激。提前谢谢你。

原始代码:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView

Builder.load_string('''
<RV>:
    viewclass: 'Label'
    RecycleBoxLayout:
    default_size: None, dp(56)
    default_size_hint: 1, None
    size_hint_y: None
    height: self.minimum_height
    orientation: 'vertical'
''')

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]

class TestApp(App):
    def build(self):
        return RV()


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

我的失败尝试:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.recycleboxlayout import RecycleBoxLayout

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(100)]
        self.viewclass = Label
        layout = RecycleBoxLayout()
        self.add_widget(layout)

class TestApp(App):
    def build(self):
        return RV()


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

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    我一直在寻找同样的东西,我不喜欢 kv lang,并且还没有确信它比在代码中做所有事情更好。

    https://kivy.org/docs/api-kivy.uix.recycleview.html#kivy.uix.recycleview.RecycleView 的示例将按如下方式创建。

    from kivy.app import App
    from kivy.graphics import Color, Rectangle
    from kivy.uix.recycleview import RecycleView
    from kivy.uix.recycleview.views import RecycleDataViewBehavior
    from kivy.uix.label import Label
    from kivy.properties import BooleanProperty
    from kivy.uix.recycleboxlayout import RecycleBoxLayout
    from kivy.uix.behaviors import FocusBehavior
    from kivy.uix.recycleview.layout import LayoutSelectionBehavior
    
    class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                     RecycleBoxLayout):
        ''' Adds selection and focus behaviour to the view. '''
        def __init__(self, **kw):
            super().__init__(**kw, default_size=(0, 28), default_size_hint=(1, None), size_hint_y=None,
                             touch_multiselect=True, multiselect=True, orientation='vertical')
    
            self.bind(minimum_height=self._min)
    
        def _min(self, inst, val):
            self.height = val
    
    class SelectableLabel(RecycleDataViewBehavior, Label):
        ''' Add selection support to the Label '''
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
    
        def __init__(self, **kw):
            super().__init__(**kw)
            self.canvas.before.clear()
            with self.canvas.before:
                if self.selected:
                    Color(.0, 0.9, .1, .3)
                else:
                    Color(0, 0, 0, 1)
                self.rect = Rectangle(size=self.size, pos=self.pos)
            self.bind(size=self._update_rect, pos=self._update_rect)
    
        def _update_rect(self, inst, value):
            self.rect.pos = inst.pos
            self.rect.size = inst.size
    
        def refresh_view_attrs(self, rv, index, data):
            ''' Catch and handle the view changes '''
            self.index = index
            return super().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 is_selected:
                print("selection changed to {0}".format(rv.data[index]))
            else:
                print("selection removed for {0}".format(rv.data[index]))
            self.canvas.before.clear()
            with self.canvas.before:
                if self.selected:
                    Color(.0, 0.9, .1, .3)
                else:
                    Color(0, 0, 0, 1)
                self.rect = Rectangle(size=self.size, pos=self.pos)
    
    
    class RV(RecycleView):
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            self.add_widget(SelectableRecycleBoxLayout())
            self.viewclass = 'SelectableLabel'
            self.data = [{'text': str(x)} for x in range(100)]
    
    
    class TestApp(App):
        def build(self):
            return RV()
    
    if __name__ == '__main__':
        TestApp().run()
    

    KV 类中的顺序很重要。不确定 需要 在哪里,但 self.data 需要在添加小部件后进行修改。

    【讨论】:

    • 看起来很棒!!我终于找到了用 RV 做事的方法。尽管它仍未完成,但它运行良好,并且比使用 ListAdapter 模块更好。无论如何,谢谢!
    【解决方案2】:

    我不是 Kivy 方面的专家,但我强烈建议您尽可能使用 kv lang。它只不过是一个简洁的python,它会让你的代码更干净。
    如果您阅读了 RecycleBoxLayout 的文档,它的实验性很强,您应该使用有效的方法。

    话虽如此,您的代码看起来还不错,但有几个问题。

    1) 替换 self.viewclass = Labelself.viewclass = 'Label'
    2) 您尚未在 python 代码中为您的RecycleBoxLayout 指定heightsizeorientation 参数。

    【讨论】:

    • 您好,感谢您的回复。我尝试了你的建议,但没有奏效。但是,我按原样导入代码并使用它(有点像使用模块),它就像宣传的那样工作。我不高兴,但我会暂时接受它,因为 RecycleView 模块目前处于高度实验性且支持有限。所以,再次感谢。我将您的评论标记为正确。
    • 是的,我正在一步一步地试验 RV 的代码。虽然self.viewclass = 'Label' 是正确的,但对于 RecycleBoxLayout 的height,事情变得有点奇怪。我在 Google 商店中构建了一个需要大量使用 RecycleView 的应用程序,我做了同样的事情,复制了示例代码,然后从那里继续。我发现网站上的 RV 文档有点难以理解,但示例代码很容易理解
    • 嗨,再次。你能给我指点你在谷歌商店里的应用吗?您是如何设法创建一个 apk 的?
    • 当然。这里是play.google.com/store/apps/…。您可以在kivy.org/docs/guide/packaging.html 处查看有关如何为 android 打包的文档。我用的是Windows,最简单的方法是用Buildozer制作apk
    • 嗨;我一直在尝试启动应用程序,但它在启动时崩溃。我的 Android 手机很旧,但应该可以运行该应用程序。到目前为止,您有任何投诉吗?
    猜你喜欢
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多