Anonymous
Kivy RecycleView — динамическое обновление атрибутов элемента
Сообщение
Anonymous » 23 дек 2025, 15:13
Я хотел бы условно изменить внешний вид элементов в Kivy RecycleView, например. выделите элемент, если он содержит определенный текст. Я взял опубликованный пример отсюда
https://github.com/kivy/kivy/blob/maste ... ic_data.py и немного изменил его, добавив класс MyLabel, реализующий подсветку текста:
Код: Выделить всё
from random import sample, randint
from string import ascii_lowercase
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
kv = '''
:
canvas.before:
Color:
rgba: [1, .85, .85, 1]
Rectangle:
size: self.size
pos: self.pos
:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
value: ''
Label:
id: name
MyLabel:
text: root.value
:
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: 2
size_hint_y: None
height: dp(108)
padding: dp(8)
spacing: dp(16)
Button:
text: 'Populate list'
on_press: root.populate()
Button:
text: 'Sort list'
on_press: root.sort()
Button:
text: 'Clear list'
on_press: root.clear()
BoxLayout:
spacing: dp(8)
Button:
text: 'Insert new item'
on_press: root.insert(new_item_input.text)
TextInput:
id: new_item_input
size_hint_x: 0.6
hint_text: 'value'
padding: dp(10), dp(10), 0, 0
BoxLayout:
spacing: dp(8)
Button:
text: 'Update first item'
on_press: root.update(update_item_input.text)
TextInput:
id: update_item_input
size_hint_x: 0.6
hint_text: 'new value'
padding: dp(10), dp(10), 0, 0
Button:
text: 'Remove first item'
on_press: root.remove()
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)
'''
Builder.load_string(kv)
class MyLabel(Label):
def on_text(self, _, newtext):
if newtext == 'Pass':
self.canvas.before.clear()
self.canvas.before.add(Color(0,.5,0,1))
self.canvas.before.add(Rectangle(size=self.size, pos=self.pos))
class Test(BoxLayout):
def populate(self):
self.rv.data = [
{'name.text': ''.join(sample(ascii_lowercase, 6)),
'value': str(randint(0, 2000))}
for x in range(50)]
self.rv.data.append({'name.text': 'testparam','value': 'Pass'})
def sort(self):
self.rv.data = sorted(self.rv.data, key=lambda x: x['name.text'])
def clear(self):
self.rv.data = []
def insert(self, value):
self.rv.data.insert(0, {
'name.text': value or 'default value', 'value': 'unknown'})
def update(self, value):
if self.rv.data:
self.rv.data[0]['name.text'] = value or 'default new value'
self.rv.refresh_from_data()
def remove(self):
if self.rv.data:
self.rv.data.pop(0)
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
Однако это не работает должным образом. Когда я прокручиваю вверх/вниз, инструкции холста применяются к неправильным элементам, например.
Есть ли способ заставить это работать правильно? Я использую Kivy v2.3.1, Python v3.13.9 (64-разрядная версия) и Windows 10.
Подробнее здесь:
https://stackoverflow.com/questions/798 ... attributes
1766491997
Anonymous
Я хотел бы условно изменить внешний вид элементов в Kivy RecycleView, например. выделите элемент, если он содержит определенный текст. Я взял опубликованный пример отсюда https://github.com/kivy/kivy/blob/master/examples/widgets/recycleview/basic_data.py и немного изменил его, добавив класс MyLabel, реализующий подсветку текста: [code]from random import sample, randint from string import ascii_lowercase from kivy.app import App from kivy.lang import Builder from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.graphics import Color, Rectangle kv = ''' : canvas.before: Color: rgba: [1, .85, .85, 1] Rectangle: size: self.size pos: self.pos : canvas.before: Color: rgba: 0.5, 0.5, 0.5, 1 Rectangle: size: self.size pos: self.pos value: '' Label: id: name MyLabel: text: root.value : 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: 2 size_hint_y: None height: dp(108) padding: dp(8) spacing: dp(16) Button: text: 'Populate list' on_press: root.populate() Button: text: 'Sort list' on_press: root.sort() Button: text: 'Clear list' on_press: root.clear() BoxLayout: spacing: dp(8) Button: text: 'Insert new item' on_press: root.insert(new_item_input.text) TextInput: id: new_item_input size_hint_x: 0.6 hint_text: 'value' padding: dp(10), dp(10), 0, 0 BoxLayout: spacing: dp(8) Button: text: 'Update first item' on_press: root.update(update_item_input.text) TextInput: id: update_item_input size_hint_x: 0.6 hint_text: 'new value' padding: dp(10), dp(10), 0, 0 Button: text: 'Remove first item' on_press: root.remove() 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) ''' Builder.load_string(kv) class MyLabel(Label): def on_text(self, _, newtext): if newtext == 'Pass': self.canvas.before.clear() self.canvas.before.add(Color(0,.5,0,1)) self.canvas.before.add(Rectangle(size=self.size, pos=self.pos)) class Test(BoxLayout): def populate(self): self.rv.data = [ {'name.text': ''.join(sample(ascii_lowercase, 6)), 'value': str(randint(0, 2000))} for x in range(50)] self.rv.data.append({'name.text': 'testparam','value': 'Pass'}) def sort(self): self.rv.data = sorted(self.rv.data, key=lambda x: x['name.text']) def clear(self): self.rv.data = [] def insert(self, value): self.rv.data.insert(0, { 'name.text': value or 'default value', 'value': 'unknown'}) def update(self, value): if self.rv.data: self.rv.data[0]['name.text'] = value or 'default new value' self.rv.refresh_from_data() def remove(self): if self.rv.data: self.rv.data.pop(0) class TestApp(App): def build(self): return Test() if __name__ == '__main__': TestApp().run() [/code] Однако это не работает должным образом. Когда я прокручиваю вверх/вниз, инструкции холста применяются к неправильным элементам, например. [img]https://i.sstatic.net/l8ct3B9F.png[/img] Есть ли способ заставить это работать правильно? Я использую Kivy v2.3.1, Python v3.13.9 (64-разрядная версия) и Windows 10. Подробнее здесь: [url]https://stackoverflow.com/questions/79853643/kivy-recycleview-dynamically-updating-element-attributes[/url]