从文本输入更改更新kivy recycleview self.data

2024-04-16 16:21:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我还没有弄清楚如何根据UI上文本输入的更改来更新数据。我一直试图将我的代码基于以下内容:https://github.com/kivy/kivy/issues/5318

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput

import re

string_to_build_recycleview = '''
<rowTest@BoxLayout>:
    #canvas:
        # Rectangle:
            # size: self.size
            # pos: self.pos
    name_text: 'Someone Else'
    stroke_text: 'Butterfly'
    classification_text: '3'
    time_text: '9:99.99'

    BoxLayout:
        orientation: 'horizontal'
        Label:
            id: name
            text: root.name_text

        Label:
            id: stroke
            text: root.stroke_text

        ClassificationTI:
            id: classification
            padding: (8, 1, 2, 1)
            halign: 'center'
            size: (20,20)
            multiline: 'False'
            input_filter: 'int'
            text: root.classification_text
            on_text: root.classification_text = self.text

        TimeTI:
            padding: (8, 1, 2, 1)
            halign: 'center'
            size: (20,20)
            multiline: 'False'
            text: root.time_text
            #on_text: root.time_text = self.text

<RecycleViewTEST@RecycleView>:
    id: myListToTest
    scroll_type: ['bars', 'content']
    #scroll_wheel_distance: dp(114)
    bar_width: dp(10)
    viewclass: 'rowTest'

    RecycleBoxLayout:
        default_size: None, dp(20)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        spacing: dp(2)
 '''

class ClassificationTI(TextInput):
    def insert_text(self,substr,from_undo=False):
        if substr.isnumeric():
            return super(ClassificationTI, self).insert_text(substr,from_undo=from_undo)
        return super(ClassificationTI, self)

class TimeTI(TextInput):
    def insert_text(self,substr,from_undo=False):
        if substr.isnumeric() or substr == ":" or substr == ".":
            return super(TimeTI, self).insert_text(substr,from_undo=from_undo)
        return super(TimeTI, self)

class RecycleViewTEST(RecycleView):
    def __init__(self, **kwargs):
        super(RecycleViewTEST, self).__init__(**kwargs)
        Builder.load_string(string_to_build_recycleview)
        self.initial_populate()

    def on_enter(self, *args):
        self.get_real_data()

    def initial_populate(self):
        data = (('TheFirstOne', 'free', '9', '1:01.60'),('TheSecondOne', 'free', '9', '1:01.60'))
        self.data = [{'name_text':n,'stroke_text':s,'classification_text':c,'time_text':t} for n,s,c,t in data]
        print(self.data)


    def validate_classification(self,classification):
        if classification.isnumeric() and int(classification) > 14 and int(classification) < 1:
            return "Not Valid"
        return classification

    def validate_time(self,time):
        if re.match(r"([0-9]?[0-9]:)?([0-5][0-9])\.([0-9][0-9])", time) is None:
            return "Not Valid"
        return time

    def do_stuff(self):
        for i in range(len(self.data)):
            print(self.data[i])
            self.data[i]['classification_text'] = self.validate_classification(self.data[i]['classification_text'])
            self.data[i]['time_text'] = self.validate_time(self.data[i]['time_text'])
            print(self.data[i])
        self.refresh_from_data()

string_to_build_the_form = '''
<TheForm>:
    BoxLayout:
        orientation: 'vertical'
        BoxLayout:
            orientation: 'horizontal'
            Label:
                size_hint: (None, None)
                size: (200, 27)
                text: '[u]Name[/u]'
                markup: True
            Label:
                size_hint: (None, None)
                size: (200, 27)
                text: '[u]Stroke[/u]'
                markup: True
            Label:
                size_hint: (None, None)
                size: (190, 27)
                text: '[u]Class[/u]'
                markup: True
            Label:
                size_hint: (None, None)
                size: (200, 27)
                text: '[u]Time (mm:ss.hh)[/u]'
                markup: True

        BoxLayout:
            size_hint: (1,None)
            RecycleViewTEST:
                id: myListToTest

        BoxLayout:
            orientation: 'horizontal'

            Button:
                size_hint: (None,None)
                size: (150,50)
                text: "Validate"
                on_release: root.validate()

            Button:
                id: save_recalc
                size_hint: (None,None)
                size: (150,50)
                text: "Save & Recalculate"
                disabled: True

'''


class TheForm(BoxLayout):
    def __init__(self, **kwargs):
        super(TheForm, self).__init__(**kwargs)
    Builder.load_string(string_to_build_the_form)

    def validate(self, *args):
        self.ids.myListToTest.do_stuff()
        self.ids.save_recalc.disabled = False


class TheTEST(App):
    def build(self):
        sm = TheForm()
        return sm

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

这是在我更改值文本输入框之后。before是指验证分类和时间,然后更改数据。执行validate()后,textinput文本返回到原始数字:

之前:{'name_text':'TheFirstOne','stroke_text':'free','classification_text':'9','time_text':'1:01.60'}

之后:{'name_text':'TheFirstOne','stroke_text':'free','classification_text':'9','time_text':'1:01.60'}

之前:{'name_text':'theseconde','stroke_text':'free','classification_text':'9','time_text':'1:01.60'}

之后:{'name_text':'theseconde','stroke_text':'free','classification_text':'9','time_text':'1:01.60'}

我错过了什么?谢谢你的帮助


Tags: textnamefromselfnonedatasizereturn
1条回答
网友
1楼 · 发布于 2024-04-16 16:21:08

我从Kivy discord论坛得到了答案。关键是将索引传递给row小部件,以便他们可以更改其行的数据。我认为这应该适用于recycleview对象中的任何复杂小部件。希望这对别人有帮助

from kivy.app import App
from kivy.properties import ObjectProperty, NumericProperty, ListProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.textinput import TextInput
from kivy.lang.builder import Builder
KV = """
<RecycleItem>:
    on_text: if root.owner != None: self.owner.data[self.index]['text'] = self.text

RecycleView:
    data: app.data
    viewclass: 'RecycleItem'
    RecycleBoxLayout:
        spacing: 10
        default_size: None, dp(80)
        default_size_hint: 1, None
        orientation: 'vertical'
        size_hint_y: None
        height: self.minimum_height
"""

class RecycleItem(RecycleDataViewBehavior,TextInput):
    owner = ObjectProperty()
    index = NumericProperty(0)

    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        print("INDEXXXXXX: ",self.index)
        return super(RecycleItem, self).refresh_view_attrs(rv, index, data)

class Test(App):
    data = ListProperty()

    def build(self):
        self.data = [{"text": "Label "+str(x), 'owner': self} for x in range(20)]
        return Builder.load_string(KV)

Test().run()

相关问题 更多 >