我将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()
答案 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,没问题。
我希望它能对某人有所帮助。