簡體   English   中英

更新 kivy recycleview self.data from textinput change

[英]Update kivy recycleview self.data from textinput change

我無法弄清楚如何從 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()

這是在我更改值文本輸入框之后。 之前是指驗證分類和時間然后更改數據。 執行 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':'TheSecondOne','stroke_text':'free','classification_text':'9','time_text':'1:01.60'}

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

我在這里想念什么? 謝謝您的幫助!

我從 discord 上的 Kivy 論壇得到了答案。 關鍵是將索引傳遞給行小部件,以便他們可以更改行的數據。 我認為這應該適用於 recycleview object 中的任何復雜小部件。 希望這可以幫助某人。

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM