Forum Archive

Accessing ui.TableViewCells from the data_source

Phuket2

I really do have a brain freeze on this issue. For the life of me I can't remember how to recover a reference to a ui.TableViewCell lets say when the row is selected. I did search the forum but i could not see an answer. In the below code, I create the cells up front. But I have a feeling this is bad. I remember omz does some tricky things with tablecells so they can be re-used to save memory.
In my example below, I just want to toggle a checkmark on the selected row. I don't want to use ui.ListDataSource, because this is just the simple version I want to do.

Sorry in advance because I think the answer is going to be very simple.
Any help appreciated

import ui


class MyDataSource(object):

    def __init__(self, data):
        '''
        I cant remember how to get access to a ui.TableViewCell, so i created
        the cells and store them in a list. I have a feeling this is bad.
        There must be a simple way to get the cell by index.  Brain Hurts!
        '''
        self.data = data
        self.sel_item = 0
        self.cells = [ui.TableViewCell()
                      for _ in range(len(self.data))]

    def tableview_number_of_rows(self, tableview, section):
        # Return the number of rows in the section
        return len(self.data)

    def tableview_cell_for_row(self, tableview, section, row):
        # Create and return a cell for the given section/row
        cell = self.cells[row]
        cell.text_label.text = self.data[row]
        return cell

    def tableview_did_select(self, tableview, section, row):
        # Called when a row was selected.
        self.select_row(row)
        pass

    def tableview_did_deselect(self, tableview, section, row):
        # Called when a row was de-selected (in multiple selection mode).
        pass

    def select_row(self, sel_row):
        for cell in self.cells:
            cell.accessory_type = ""

        self.cells[sel_row].accessory_type = 'checkmark'
        self.sel_item = sel_row


def get_table(items):
    tbl = ui.TableView(frame=(0, 0, 300, 400))
    tbl.data_source = MyDataSource(items)
    tbl.delegate = tbl.data_source
    return tbl


if __name__ == '__main__':
    v = get_table(['Ian', 'Fred', 'John', 'Paul'])
    v.present(style='sheet', animated=False)
JonB

I think part of the concept is mvc where your datasource doesn't need access to the cell (presentation layer) itself -- instead cellforrow produces the cell looking the way you want, and you reload if you want to change it.

in practice, what you've got seems reasonable.

Phuket2

@JonB , thanks for the answer. I was finding it hard to believe I had not had this problem before. But it sort of makes sense as I rarely finish anything to a full working something that does anything useful or complete.

@omz, could you weigh in regards if this approach is ok. Look, for what I am doing at the moment i am at max going to needs around 10 rows. But is there a point where this approach could or start to fail because you start to re-use ui.TableViewCells?
I would like to know. I see myself doing a lot more with ui.TableView. I personally think being to update the cell after creation is important. Eg from an web request etc..... Not all can be known at creation time. Anyway interested in what you think the right approach is

omz

@Phuket2 If you just have 10 cells or so, it's totally fine to initialize them all at once. That's exactly what dialogs.form_dialog() is doing btw. This can become a problem if you have hundreds of cells, but that's typically not the case in a settings-style UI.

Phuket2

@omz , ok thanks for the info.

Phuket2

Oh, btw. I might have even seen this before. Sometimes its a blur for me if I have worked something out for the first time, or if I have seen it before. I have looked at dialogs before, but it was a long time ago. Good chance i would not have understood what it was doing anyway. But I think its a good idea to go and re-look with fresh eyes and mind. Learn some new things