代码之家  ›  专栏  ›  技术社区  ›  tomion

Kivy中的RecycleView模块

  •  1
  • tomion  · 技术社区  · 8 年前

    新成员,第一个职位。我会尽量具体和明确。以下代码摘自kivy的网页 RecycleView module . 我希望使用这段代码,但是,我不希望使用KV lang和生成器,而是用纯Python 3编写代码。我试图将RecycleBoxLayout类添加为一个小部件,但完全失败了,结果只是一个黑色窗口。只有添加了“viewclass”才起作用。显然,这里有一些我不理解或遗漏的东西。我还附上了我重写代码的尝试。

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

    原始代码:

    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()
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   grayhatter    8 年前

    我也在寻找同样的东西,我不喜欢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级的顺序很重要。不确定什么 需要 去哪里,但自我。添加小部件后,需要修改数据。

        2
  •  0
  •   DJay    8 年前

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

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

    1) 更换 self.viewclass = Label 具有 self.viewclass = 'Label' 和
    2) 您尚未指定 height , size 和 orientation 您的 循环利用布局 在python代码中。