How to do single row selection in kivyMD DataTables

Question:

I am using kivyMD DataTables widget to display my data and allow single row can be selected to do some further edit.
The following is my test case. I have encountered several problems.

  1. I use on_row_press event to treat the selection, but I found only clicking on the first column will give check box’s state change.
  2. I use instance_table.table_data.select_all('normal') to cancel all existed selections. But the cursor always moves to the bottom row but not the selected row.
  3. I found the instance_row.state keeps down whatever I select or deselect one row. How can I get the row selection state?

Could you help me out? Thanks.

from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
from kivy.logger import Logger

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.datatables.datatables import CellRow

kv = '''
BoxLayout:
    orientation: "vertical"
    BoxLayout:
        id:button_tab
        size_hint_y:None
        height: dp(48)

        MDFlatButton:
            text: "Hello <3"
            on_release:
                app.update_row_data()

    BoxLayout:
        id:body

'''


class Example(MDApp):
    def build(self):
        self.data_tables = MDDataTable(
            # MDDataTable allows the use of size_hint
            size_hint=(0.8, 0.7),
            use_pagination=True,
            check=True,
            column_data=[
                ("No.", dp(30)),
                ("Status", dp(30)),
                ("Signal Name", dp(60)),
                ("Severity", dp(30)),
                ("Stage", dp(30)),
                ("Schedule", dp(30)),
                ("Team Lead", dp(30))
            ],
            row_data=[
                ("1", ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"),
                 "Astrid: NE shared managed", "Medium", "Triaged", "0:33",
                 "Chase Nguyen"),
                ("2", ("alert-circle", [1, 0, 0, 1], "Offline"),
                 "Cosmo: prod shared ares", "Huge", "Triaged", "0:39",
                 "Brie Furman"),
                ("3", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Phoenix: prod shared lyra-lists", "Minor",
                 "Not Triaged", "3:12", "Jeremy lake"),
                ("4", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Sirius: NW prod shared locations",
                 "Negligible",
                 "Triaged", "13:18", "Angelica Howards"),
                ("5", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Sirius: prod independent account",
                 "Negligible",
                 "Triaged", "22:06", "Diane Okuma"),
            ]
        )
        self.data_tables.bind(on_row_press=self.on_row_press)
        root = Builder.load_string(kv)
        root.ids.body.add_widget(self.data_tables)
        return root

    def on_row_press(self, instance_table, instance_row):
        '''Called when a table row is clicked.'''
        print(instance_table, instance_row)
        if instance_row.ids.check.state == 'normal':
            instance_table.table_data.select_all('normal')
            instance_row.ids.check.state = 'down'
        else:
            instance_table.table_data.select_all('normal')
            # instance_row.ids.check.state = 'normal'
        print("instance_row.state:",instance_row.state)


Example().run()

Asked By: Jilong Yin

||

Answers:

after digging into the kivyMD, I got the solution

"""
@author:
@file:test_table_check2.py
@time:2022/09/079:39
@file_desc
"""
from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
from kivy.logger import Logger

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable

kv = '''
BoxLayout:
    orientation: "vertical"
    BoxLayout:
        id:button_tab
        size_hint_y:None
        height: dp(48)

        MDFlatButton:
            text: "Hello <3"
            on_release:
                app.update_row_data()

    BoxLayout:
        id:body

'''


class Example(MDApp):
    def build(self):
        self.data_tables = MDDataTable(
            # MDDataTable allows the use of size_hint
            size_hint=(0.8, 0.7),
            use_pagination=True,
            check=True,
            column_data=[
                ("No.", dp(30)),
                ("Status", dp(30)),
                ("Signal Name", dp(60)),
                ("Severity", dp(30)),
                ("Stage", dp(30)),
                ("Schedule", dp(30)),
                ("Team Lead", dp(30))
            ],
            row_data=[
                ("1", ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"),
                 "Astrid: NE shared managed", "Medium", "Triaged", "0:33",
                 "Chase Nguyen"),
                ("2", ("alert-circle", [1, 0, 0, 1], "Offline"),
                 "Cosmo: prod shared ares", "Huge", "Triaged", "0:39",
                 "Brie Furman"),
                ("3", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Phoenix: prod shared lyra-lists", "Minor",
                 "Not Triaged", "3:12", "Jeremy lake"),
                ("4", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Sirius: NW prod shared locations",
                 "Negligible",
                 "Triaged", "13:18", "Angelica Howards"),
                ("5", (
                    "checkbox-marked-circle",
                    [39 / 256, 174 / 256, 96 / 256, 1],
                    "Online"), "Sirius: prod independent account",
                 "Negligible",
                 "Triaged", "22:06", "Diane Okuma"),

            ],
            sorted_on="Schedule",
            sorted_order="ASC",
            elevation=2
        )
        self.data_tables.bind(on_row_press=self.on_row_press)
        root = Builder.load_string(kv)
        root.ids.body.add_widget(self.data_tables)
        return root

    def on_row_press(self, instance_table, instance_row):
        '''Called when a table row is clicked.'''
        print(instance_table, instance_row)
        index = instance_row.index
        cols_num = len(instance_table. column_data)
        row_num = int(index/cols_num)
        col_num = index%cols_num
        cell_row =instance_table.table_data.view_adapter.get_visible_view(row_num*cols_num)
        if cell_row.ids.check.state == 'normal':
            instance_table.table_data.select_all('normal')
            cell_row.ids.check.state = 'down'
        else:
            cell_row.ids.check.state = 'normal'
        instance_table.table_data.on_mouse_select(instance_row)



Example().run()
Answered By: Jilong Yin
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.