Search code examples
pythonkivytextinput

Kivy - Editable RecycleView


I'm trying to create an editable table with the RecycleView widget using a TextInput widget as the individual element in Kivy. By looking at the examples and some posts on the web, I was able to write a table that takes input from the user.

Now I'm trying to get which row did the user edit. I could find events for on_text of the text input but that doesn't give information about the row number. Also I tried looking at the events available for the RecycleView but couldn't get much help from it.

Could anyone of you guide me in the right path. I'm fairly new to kivy. I have attached herewith, a simple example that I'm working on.

from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.lang import Builder


Builder.load_string('''
<Row@BoxLayout>:
    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


<RV>:
    id: rv
    viewclass: 'Row'
    scroll_type: ['bars', 'content']
    scroll_wheel_distance: dp(114)
    bar_width: dp(10)
    RecycleGridLayout:
        cols:3
        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):

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'itemText':'1'}, {'itemText':'John'}, {'itemText':'K'}, {'itemText':'2'}, {'itemText':'David'}, {'itemText':'P'}]


class rvTestApp(App):

    def build(self):
        return RV()

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

Solution

  • SP SP's answer gets a way to work around this problem but I found another way (hoping this to be a better one) to get the row index.

    Adding the below over-riding functions into the row class helped me get the row index when ever the user clicks on the textinput.

    class Row(BoxLayout, RecycleDataViewBehavior):
    index = None
    
    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):
        if super(Row, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos):
            global rowIndex
            rowIndex = self.index
    

    Thanks again for helping me with your suggestions. Posting my solution in case if any one else is facing the same problem.