#python-3.x #kivy #kivy-language
#python-3.x #kivy #kivy-language
Вопрос:
У меня есть просмотр recycle, который состоит только из текстовых полей. Когда вы вводите что-либо в текстовое поле, прокрутите вниз и прокрутите обратно вверх, текст исчезнет.
Я попытался обновить список данных в режиме рециркуляции, но при прокрутке он просто сбрасывает его снова. Я создал отдельную программу только с представлением recycle, чтобы попытаться провести эксперимент.
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty, ListProperty
from kivy.clock import Clock
Builder.load_string('''
<Row>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
itemText: ''
TextInput:
id:CellText
text:root.itemText
<Row2>
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
itemText: ''
TextInput:
id:CellText
text:root.itemText
TextInput:
id:CellText
text:root.itemText2
<RV>:
id: rv
viewclass: 'Row'
pos: 10,-50
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
RecycleGridLayout:
cols:6
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: dp(1)
''')
class RV(RecycleView):
list_items = ListProperty([])
numRows = 16
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'itemText': "1", 'paren': self, 'index':0},
{'itemText': "1", 'paren': self, 'index':0},
{'itemText': '0','paren': self, 'index':2},
{'itemText': "1", 'paren': self, 'index':0},
{'itemText': '0','paren': self, 'index':2},
{'itemText': '0','paren': self, 'index':2}]
for x in range(2,32):
self.data.extend([{'itemText': str(x), 'paren': self, 'index':6}])
self.data.extend([{'itemText': "1", 'paren': self, 'index':6}])
self.data.extend([{'itemText': "0", 'paren': self, 'index': 6}])
self.data.extend([{'itemText': "1", 'paren': self, 'index':6}])
self.data.extend([{'itemText': "0", 'paren': self, 'index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'index': 6}])
def which_edit(self, *args):
'''This will print the index of the box which is currently edited'''
#print args[0].parent.index
class Row(BoxLayout):
paren = ObjectProperty() #the instance of the rv
def __init__(self, **kwargs):
super(Row, self).__init__(**kwargs)
Clock.schedule_once(self.update)
def update(self, *args):
self.paren.list_items.append(self)
self.ids.CellText.bind(text=self.paren.which_edit)
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()
Ответ №1:
Проблема 1
Я попытался обновить список данных в режиме рециркуляции, но при прокрутке он просто сбрасывает его снова.
Основная причина
Все, что вводится в TextInput, не отражается в self.data
. Из-за этого всякий раз, когда происходит прокрутка, TextInput обновляется из self.data
.
Проблема 2
Перезаписано index
например {'itemText': "1", 'paren': self, 'index':0},
Объяснение
index
это зарезервированные атрибуты для RecycleView. Он используется для идентификации каждой ячейки в столбцах.
Решение
файл kv
Обновляйте self.data всякий раз, когда в TextInput вносятся какие-либо изменения.
Фрагменты
TextInput:
id:CellText
text:root.itemText
on_text:
app.root.data[root.index]['itemText'] = self.text
Скрипт на Python
Заменить index
на Index
Фрагменты
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': '0', 'paren': self, 'Index': 2},
{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': '0', 'paren': self, 'Index': 2},
{'itemText': '0', 'paren': self, 'Index': 2}]
for x in range(2, 32):
self.data.extend([{'itemText': str(x), 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "1", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "1", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
Пример
main.py
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
Builder.load_string('''
<Row>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
itemText: ''
TextInput:
id:CellText
text:root.itemText
on_text:
#root.which_edit(args)
app.root.data[root.index]['itemText'] = self.text
<RV>:
id: rv
viewclass: 'Row'
pos: 10,-50
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
RecycleGridLayout:
cols:6
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: dp(1)
''')
class Row(RecycleDataViewBehavior, BoxLayout):
pass
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(Row, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(Row, 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]))
def which_edit(self, *args):
'''This will print the index of the box which is currently edited'''
print(f'args={args}')
class RV(RecycleView):
numRows = 16
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': '0', 'paren': self, 'Index': 2},
{'itemText': "1", 'paren': self, 'Index': 0},
{'itemText': '0', 'paren': self, 'Index': 2},
{'itemText': '0', 'paren': self, 'Index': 2}]
for x in range(2, 32):
self.data.extend([{'itemText': str(x), 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "1", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "1", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
self.data.extend([{'itemText': "0", 'paren': self, 'Index': 6}])
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()