Kivy:RecycleView在Python实现时不显示,但在KV语言编写时有效

问题描述 投票:0回答:1

我是 Kivy 的新手。通过构建一个简单的应用程序来学习。

我想在顶部显示项目列表(为此使用 RecycleView 小部件)。底部将是一个文本框(使用 TextInput 小部件)和按钮(使用 Button 小部件)来输入新项目。下面给出了该应用程序的代码。

应用程序运行时,会显示文本框和按钮,但不会显示回收视图。

如果我使用 builder.load (下面给出的字符串)而不是 BulletListLayout 的类定义(与 RecycleBoxLayout 的 init 中的参数完全相同),它就可以工作。我有意尝试让它在纯 python 中工作,以便我了解 KV 语言如何映射到 python 对象。

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

请帮助我理解为什么当一切都是Python时它不起作用。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview import RecycleView
from journal.backend.daily.logic import GetAllBulletsLogic, AddBulletLogic
from kivy import metrics


class NewBullet(TextInput):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.hint_text = "Enter your new bullet here"
        self.focus = True

class BulletListLayout(RecycleBoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        print('in bullet list layout')
        self.default_size= (None, metrics.dp(56))
        self.default_size_hint= (1, None)
        self.size_hint_y= None
        self.height= self.minimum_height
        self.orientation= 'vertical'


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

class NewBulletEntryView(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.height=metrics.dp(40)
        self.size_hint_y=None
        self.new_bullet = NewBullet(size_hint_x=0.9)
        self.button = Button(text="Add", size_hint_x=0.1)
        self.add_widget(self.new_bullet)
        self.add_widget(self.button)

class DailyLogApp(App):
    def build(self):
        layout = BoxLayout(orientation="vertical")
        bullet_list = BulletList(data=[{'text': str(x)} for x in range(20)] )
        new_bullet_entry = NewBulletEntryView()
        layout.add_widget(bullet_list)
        layout.add_widget(new_bullet_entry)
        return layout

if __name__ == "__main__":
    DailyLogApp().run()
python kivy kivy-language kivy-recycleview
1个回答
0
投票

build()
BulletListLayout
方法中,将
height
设置为
self.minimum_height

self.height= self.minimum_height

这会将

height
BulletListLayout
设置为其在计算此代码时的
minimum_height
。由于
BulletListLayout
此时没有子节点,因此
minimum_height
为 0,因此此代码将
height
设置为 0,并且该高度永远不会更新。

kv
代码所做的事情之一是创建绑定。所以当你有
kv
:

height: self.minimum_height

Kivy 使用上述信息创建一个绑定,以便在

height
发生变化时修改
minimum_height
。这仅适用于
Properties

等效的Python代码(可以放在

__init__()
BulletListLayout
方法中)是:

self.bind(minimum_height=self.setter('height'))

另一个小细节是,在设置

viewclass
之前,先设置
BulletList
layout_manager
。可能是
RecycleView
中的错误,但是您必须在设置
layout_manager
之前设置
viewclass
,否则
viewclass
不会传递到
layout_manager

所以,我认为以下类定义将使您的代码正常工作:

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


class BulletListLayout(RecycleBoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.default_size= (None, metrics.dp(56))
        self.default_size_hint= (1, None)
        self.size_hint_y= None
        # self.height= self.minimum_height
        self.orientation= 'vertical'
        self.bind(minimum_height=self.setter('height'))
© www.soinside.com 2019 - 2024. All rights reserved.