DataTables#
See also Data tables display sets of data across rows and columns. Note MDDataTable allows developers to sort the data provided by column.
This happens thanks to the use of an external function that you can bind
while you’re defining the table columns. Be aware that the sorting function
must return a 2 value list in the format of: [Index, Sorted_Row_Data] This is because the index list is needed to allow MDDataTable to keep track
of the selected rows. and, after the data is sorted, update the row
checkboxes.
API - kivymd.uix.datatables.datatables
#
- class kivymd.uix.datatables.datatables.MDDataTable(**kwargs)#
Datatable class.
For more information, see in the
ThemableBehavior
andAnchorLayout
classes documentation.- Events:
on_row_press
Called when a table row is clicked.
on_check_press
Called when the check box in the table row is checked.
Use events as follows
from kivy.metrics import dp from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable from kivymd.uix.screen import MDScreen class Example(MDApp): def build(self): self.data_tables = MDDataTable( use_pagination=True, check=True, column_data=[ ("No.", dp(30)), ("Status", dp(30)), ("Signal Name", dp(60), self.sort_on_signal), ("Severity", dp(30)), ("Stage", dp(30)), ("Schedule", dp(30), self.sort_on_schedule), ("Team Lead", dp(30), self.sort_on_team), ], 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) self.data_tables.bind(on_check_press=self.on_check_press) screen = MDScreen() screen.add_widget(self.data_tables) return screen def on_row_press(self, instance_table, instance_row): '''Called when a table row is clicked.''' print(instance_table, instance_row) def on_check_press(self, instance_table, current_row): '''Called when the check box in the table row is checked.''' print(instance_table, current_row) # Sorting Methods: # since the https://github.com/kivymd/KivyMD/pull/914 request, the # sorting method requires you to sort out the indexes of each data value # for the support of selections. # # The most common method to do this is with the use of the builtin function # zip and enumerate, see the example below for more info. # # The result given by these funcitons must be a list in the format of # [Indexes, Sorted_Row_Data] def sort_on_signal(self, data): return zip(*sorted(enumerate(data), key=lambda l: l[1][2])) def sort_on_schedule(self, data): return zip( *sorted( enumerate(data), key=lambda l: sum( [ int(l[1][-2].split(":")[0]) * 60, int(l[1][-2].split(":")[1]), ] ), ) ) def sort_on_team(self, data): return zip(*sorted(enumerate(data), key=lambda l: l[1][-1])) Example().run()
- column_data#
Data for header columns.
from kivy.metrics import dp from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable from kivy.uix.anchorlayout import AnchorLayout class Example(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = AnchorLayout() self.data_tables = MDDataTable( size_hint=(0.7, 0.6), use_pagination=True, check=True, # name column, width column, sorting function column(optional), custom tooltip column_data=[ ("No.", dp(30), None, "Custom tooltip"), ("Status", dp(30)), ("Signal Name", dp(60)), ("Severity", dp(30)), ("Stage", dp(30)), ("Schedule", dp(30), lambda *args: print("Sorted using Schedule")), ("Team Lead", dp(30)), ], ) layout.add_widget(self.data_tables) return layout Example().run()
from kivy.metrics import dp from kivymd.app import MDApp from kivymd.uix.anchorlayout import MDAnchorLayout from kivymd.uix.datatables import MDDataTable class Example(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" return MDAnchorLayout( MDDataTable( size_hint=(0.7, 0.6), use_pagination=True, check=True, # name column, width column, sorting function column(optional) column_data=[ ("No.", dp(30)), ("Status", dp(30)), ("Signal Name", dp(60)), ("Severity", dp(30)), ("Stage", dp(30)), ("Schedule", dp(30), lambda *args: print("Sorted using Schedule")), ("Team Lead", dp(30)), ], ) ) Example().run()
column_data
is anListProperty
and defaults to [].Note
The functions which will be called for sorting must accept a data argument and return the sorted data. Incoming data format will be similar to the provided row_data except that it’ll be all list instead of tuple like below. Any icon provided initially will also be there in this data so handle accordingly.
[ [ "1", ["icon", "No Signal"], "Astrid: NE shared managed", "Medium", "Triaged", "0:33", "Chase Nguyen", ], [ "2", "Offline", "Cosmo: prod shared ares", "Huge", "Triaged", "0:39", "Brie Furman", ], [ "3", "Online", "Phoenix: prod shared lyra-lists", "Minor", "Not Triaged", "3:12", "Jeremy lake", ], [ "4", "Online", "Sirius: NW prod shared locations", "Negligible", "Triaged", "13:18", "Angelica Howards", ], [ "5", "Online", "Sirius: prod independent account", "Negligible", "Triaged", "22:06", "Diane Okuma", ], ]
You must sort inner lists in ascending order and return the sorted data in the same format.
- row_data#
Data for rows. To add icon in addition to a row data, include a tuple with This property stores the row data used to display each row in the DataTable To show an icon inside a column in a row, use the folowing format in the row’s columns.
Format:
(“MDicon-name”, [icon color in rgba], “Column Value”)
Example:
For a more complex example see below.
from kivy.metrics import dp from kivy.uix.anchorlayout import AnchorLayout from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable class Example(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = AnchorLayout() data_tables = MDDataTable( size_hint=(0.9, 0.6), column_data=[ ("Column 1", dp(20)), ("Column 2", dp(30)), ("Column 3", dp(50), self.sort_on_col_3), ("Column 4", dp(30)), ("Column 5", dp(30)), ("Column 6", dp(30)), ("Column 7", dp(30), self.sort_on_col_2), ], row_data=[ # The number of elements must match the length # of the `column_data` list. ( "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", ), ], ) layout.add_widget(data_tables) return layout def sort_on_col_3(self, data): return zip( *sorted( enumerate(data), key=lambda l: l[1][3] ) ) def sort_on_col_2(self, data): return zip( *sorted( enumerate(data), key=lambda l: l[1][-1] ) ) Example().run()
row_data
is anListProperty
and defaults to [].
- sorted_on#
Column name upon which the data is already sorted.
If the table data is showing an already sorted data then this can be used to indicate upon which column the data is sorted.
sorted_on
is anStringProperty
and defaults to ‘’.
- sorted_order#
Order of already sorted data. Must be one of ‘ASC’ for ascending or ‘DSC’ for descending order.
sorted_order
is anOptionProperty
and defaults to ‘ASC’.
- check#
Use or not use checkboxes for rows.
check
is anBooleanProperty
and defaults to False.
- use_pagination#
Use page pagination for table or not.
from kivy.metrics import dp from kivy.uix.anchorlayout import AnchorLayout from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable class Example(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = AnchorLayout() data_tables = MDDataTable( size_hint=(0.9, 0.6), use_pagination=True, column_data=[ ("No.", dp(30)), ("Column 1", dp(30)), ("Column 2", dp(30)), ("Column 3", dp(30)), ("Column 4", dp(30)), ("Column 5", dp(30)), ], row_data=[ (f"{i + 1}", "1", "2", "3", "4", "5") for i in range(50) ], ) layout.add_widget(data_tables) return layout Example().run()
use_pagination
is anBooleanProperty
and defaults to False.
- elevation#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.elevation
attribute.elevation
is anNumericProperty
and defaults to 4.
- shadow_radius#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_radius
attribute.New in version 1.2.0.
shadow_radius
is anVariableListProperty
and defaults to [6].
- shadow_softness#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_softness
attribute.New in version 1.2.0.
shadow_softness
is anNumericProperty
and defaults to 12.
- shadow_softness_size#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_softness_size
attribute.New in version 1.2.0.
shadow_softness_size
is anBoundedNumericProperty
and defaults to 2.
- shadow_offset#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_offset
attribute.New in version 1.2.0.
shadow_offset
is anListProperty
and defaults to (0, 2).
- shadow_color#
See
kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_color
attribute.New in version 1.2.0.
shadow_color
is anColorProperty
and defaults to [0, 0, 0, 0.6].
- rows_num#
The number of rows displayed on one page of the table.
rows_num
is anNumericProperty
and defaults to 10.
Menu position for selecting the number of displayed rows. Available options are ‘center’, ‘auto’.
Center
Auto
pagination_menu_pos
is anOptionProperty
and defaults to ‘center’.
Menu height for selecting the number of displayed rows.
240dp
pagination_menu_height
is anNumericProperty
and defaults to ‘140dp’.
- background_color#
Background color in the format (r, g, b, a) or string format. See
background_color
.Use markup strings#
from kivy.metrics import dp from kivy.uix.anchorlayout import AnchorLayout from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable class Example(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = AnchorLayout() data_tables = MDDataTable( size_hint=(0.9, 0.6), use_pagination=True, column_data=[ ("No.", dp(30)), ("Column 1", dp(30)), ("[color=#52251B]Column 2[/color]", dp(30)), ("Column 3", dp(30)), ("[size=24][color=#C042B8]Column 4[/color][/size]", dp(30)), ("Column 5", dp(30)), ], row_data=[ ( f"{i + 1}", "[color=#297B50]1[/color]", "[color=#C552A1]2[/color]", "[color=#6C9331]3[/color]", "4", "5", ) for i in range(50) ], ) layout.add_widget(data_tables) return layout Example().run()
background_color
is aColorProperty
and defaults to [0, 0, 0, 0].
- background_color_header#
Background color in the format (r, g, b, a) or string format for
TableHeader
class.New in version 1.0.0.
self.data_tables = MDDataTable( ..., background_color_header="#65275d", )
background_color_header
is aColorProperty
and defaults to None.
- background_color_cell#
Background color in the format (r, g, b, a) or string format for
CellRow
class.New in version 1.0.0.
self.data_tables = MDDataTable( ..., background_color_header="#65275d", background_color_cell="#451938", )
background_color_cell
is aColorProperty
and defaults to None.
- background_color_selected_cell#
Background selected color in the format (r, g, b, a) or string format for
CellRow
class.New in version 1.0.0.
self.data_tables = MDDataTable( ..., background_color_header="#65275d", background_color_cell="#451938", background_color_selected_cell="e4514f", )
background_color_selected_cell
is aColorProperty
and defaults to None.
- effect_cls#
Effect class. See
kivy/effects
package for more information.New in version 1.0.0.
effect_cls
is anObjectProperty
and defaults toStiffScrollEffect
.
- update_row_data(self, instance_data_table, data: list)#
Called when a the widget data must be updated.
Remember that this is a heavy function. since the whole data set must be updated. you can get better results calling this metod with in a coroutine.
- add_row(self, data: list | tuple)#
Added new row to common table. Argument data is the row data from the list
row_data
.Add/remove row
from kivy.metrics import dp from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.floatlayout import MDFloatLayout from kivymd.uix.button import MDRaisedButton class Example(MDApp): data_tables = None def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = MDFloatLayout() # root layout # Creating control buttons. button_box = MDBoxLayout( pos_hint={"center_x": 0.5}, adaptive_size=True, padding="24dp", spacing="24dp", ) for button_text in ["Add row", "Remove row"]: button_box.add_widget( MDRaisedButton( text=button_text, on_release=self.on_button_press ) ) # Create a table. self.data_tables = MDDataTable( pos_hint={"center_y": 0.5, "center_x": 0.5}, size_hint=(0.9, 0.6), use_pagination=False, column_data=[ ("No.", dp(30)), ("Column 1", dp(40)), ("Column 2", dp(40)), ("Column 3", dp(40)), ], row_data=[("1", "1", "2", "3")], ) # Adding a table and buttons to the toot layout. layout.add_widget(self.data_tables) layout.add_widget(button_box) return layout def on_button_press(self, instance_button: MDRaisedButton) -> None: '''Called when a control button is clicked.''' try: { "Add row": self.add_row, "Remove row": self.remove_row, }[instance_button.text]() except KeyError: pass def add_row(self) -> None: last_num_row = int(self.data_tables.row_data[-1][0]) self.data_tables.add_row((str(last_num_row + 1), "1", "2", "3")) def remove_row(self) -> None: if len(self.data_tables.row_data) > 1: self.data_tables.remove_row(self.data_tables.row_data[-1]) Example().run()
Deleting checked rows#
from kivy.metrics import dp from kivy.lang import Builder from kivy.clock import Clock from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable from kivymd.uix.screen import MDScreen KV = ''' MDBoxLayout: orientation: "vertical" padding: "56dp" spacing: "24dp" MDData: id: table_screen MDRaisedButton: text: "DELETE CHECKED ROWS" on_release: table_screen.delete_checked_rows() ''' class MDData(MDScreen): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = [ ["1", "Asep Sudrajat", "Male", "Soccer"], ["2", "Egy", "Male", "Soccer"], ["3", "Tanos", "Demon", "Soccer"], ] self.data_tables = MDDataTable( use_pagination=True, check=True, column_data=[ ("No", dp(30)), ("No Urut.", dp(30)), ("Alamat Pengirim", dp(30)), ("No Surat", dp(60)), ] ) self.data_tables.row_data = self.data self.add_widget(self.data_tables) def delete_checked_rows(self): def deselect_rows(*args): self.data_tables.table_data.select_all("normal") for data in self.data_tables.get_row_checks(): self.data_tables.remove_row(data) Clock.schedule_once(deselect_rows) class MyApp(MDApp): def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" return Builder.load_string(KV) MyApp().run()
New in version 1.0.0.
- remove_row(self, data: list | tuple)#
Removed row from common table. Argument data is the row data from the list
row_data
.See the code in the doc string for the
add_row
method for more information.New in version 1.0.0.
- update_row(self, old_data: list | tuple, new_data: list | tuple)#
Updates a table row. Argument old_data/new_data is the row data from the list
row_data
.Update row
from kivy.metrics import dp from kivymd.app import MDApp from kivymd.uix.datatables import MDDataTable from kivymd.uix.floatlayout import MDFloatLayout from kivymd.uix.button import MDRaisedButton class Example(MDApp): data_tables = None def build(self): self.theme_cls.theme_style = "Dark" self.theme_cls.primary_palette = "Orange" layout = MDFloatLayout() layout.add_widget( MDRaisedButton( text="Change 2 row", pos_hint={"center_x": 0.5}, on_release=self.update_row, y=24, ) ) self.data_tables = MDDataTable( pos_hint={"center_y": 0.5, "center_x": 0.5}, size_hint=(0.9, 0.6), use_pagination=False, column_data=[ ("No.", dp(30)), ("Column 1", dp(40)), ("Column 2", dp(40)), ("Column 3", dp(40)), ], row_data=[(f"{i + 1}", "1", "2", "3") for i in range(3)], ) layout.add_widget(self.data_tables) return layout def update_row(self, instance_button: MDRaisedButton) -> None: self.data_tables.update_row( self.data_tables.row_data[1], # old row data ["2", "A", "B", "C"], # new row data ) Example().run()
New in version 1.0.0.
- on_row_press(self, instance_cell_row)#
Called when a table row is clicked.
- on_check_press(self, row_data: list)#
Called when the check box in the table row is checked.
- Parameters:
row_data – One of the elements from the
MDDataTable.row_data
list.
- get_row_checks(self)#
Returns all rows that are checked.