Kivy RecycleView中的行重复

时间:2018-07-24 23:41:55

标签: python kivy recycle

我将Kivy RecycleView与Row类一起使用以创建可编辑的值表。问题是,当我在一行中键入一个条目时,该值也会在表格中更下方的其他行中显示。在调试器中,编辑一行将正确显示RecycleView.data仅更新了我键入的那一行,而不更新了它们出现的其他行,因此UI和基础数据之间似乎断开了连接。无法理解这种方法可能会遗漏或误解的内容。请帮忙。谢谢!

我在以下代码的行为视频中添加了link,希望它可以自我解释。当初始行填充唯一值时,不会发生这种情况。

在视频中,该应用程序具有三个按钮。左按钮填充行的随机唯一值。这些行填充有唯一值,对其进行编辑不会引起前面提到的问题,并且行为正常。中间和右按钮分别用重复的“无”文本和空白填充行。当使用这种类型的数据填充行时,编辑这些行中的任何一行都将导致该值在滚动时反复显示在更下方。我在OSX上使用Kivy 1.10.0和Python 3.6.2。

# based on code from https://github.com/kivy/kivy/blob/master/examples/widgets/recycleview/basic_data.py

from random import sample
from string import ascii_lowercase

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

from kivy.uix.recycleview.views import RecycleDataViewBehavior

kv = """
<Row@BoxLayout>:
    canvas.before:
        Color:
            rgba: 0.5, 0.5, 0.5, 1
        Rectangle:
            size: self.size
            pos: self.pos
    value: ''
    TextInput:
        multiline: False
        text: root.value
        on_text_validate: root.update(args[0].text)

<Test>:
    canvas:
        Color:
            rgba: 0.3, 0.3, 0.3, 1
        Rectangle:
            size: self.size
            pos: self.pos
    rv: rv
    orientation: 'vertical'
    GridLayout:
        cols: 3
        rows: 1
        size_hint_y: None
        height: dp(108)
        padding: dp(8)
        spacing: dp(16)
        Button:
            text: 'Populate with text'
            on_press: root.populate_with_text()
        Button:
            text: 'Populate with same text'
            on_press: root.populate_with_same_text()
        Button:
            text: 'Populate with blanks'
            on_press: root.populate_with_blanks()
    RecycleView:
        id: rv
        scroll_type: ['bars', 'content']
        scroll_wheel_distance: dp(114)
        bar_width: dp(10)
        viewclass: 'Row'
        RecycleBoxLayout:
            default_size: None, dp(56)
            default_size_hint: 1, None
            size_hint_y: None
            height: self.minimum_height
            orientation: 'vertical'
            spacing: dp(2)
"""


class Row(RecycleDataViewBehavior, BoxLayout):
    def update(self, text):
        self.parent.parent.data[self.index]['value'] = text
        self.parent.parent.refresh_from_data()

    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        return super(Row, self).refresh_view_attrs(rv, index, data)


class Test(BoxLayout):

    def populate_with_text(self):
        self.rv.data = [{'value': ''.join(sample(ascii_lowercase, 6)), 'index': x}
                        for x in range(50)]
        self.rv.refresh_from_data()

    def populate_with_same_text(self):
        self.rv.data = [{'value': 'None', 'index': x}
                        for x in range(50)]
        self.rv.refresh_from_data()

    def populate_with_blanks(self):
        self.rv.data = [{'value': '', 'index': x}
                        for x in range(50)]
        self.rv.refresh_from_data()


Builder.load_string(kv)


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


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

1 个答案:

答案 0 :(得分:0)

我遇到了一个非常类似的问题,也许您已经按照自己的方式解决了,但是也许我可以帮助其他人。

也许您已经在Kivy github站点中注意到了与此问题相关的一些问题,但是直到现在还没有解决方案。

直到现在,我已经得出的结论是,这是奇异果中带有recycleview的错误。

我还没有找到真正的解决方案,而是找到了个人解决方法,实际上甚至没有100%的解决方法,但这对我来说却是有效的。

发布这种解决方法对我来说有点尴尬,但是要花费大量时间来解决这样一个简单的问题,会让您接受一些“替代”代码以继续前进。

因此,为说明起见,我在您的代码中在类Row @ BoxLayout中的kv文件中添加了一个焦点事件,以刷新视觉错误问题,因此最终的kv文件类如下:

<Row@BoxLayout>:
canvas.before:
    Color:
        rgba: 0.5, 0.5, 0.5, 1
    Rectangle:
        size: self.size
        pos: self.pos
value: ''
TextInput:
    multiline: False
    text: root.value
    on_text_validate: root.update(args[0].text)
    on_focus: self.text = root.value ## new line bug workaround

此额外的代码行会在错误发生后“更正”该错误,因为实际列表不受该错误影响,仅受屏幕更改的影响,因此焦点事件会使用正确的文本刷新该值。

此方法的问题是,如果您开始更改InputText中的文本并同时滚动列表,则会发生此问题,因为validate事件将在错误的行中执行,但是如果您只是更改文本并按Enter,没问题。

我希望它能对某人有所帮助。