I'm having some trouble adding the kivymd MDDataTable component as a child widget to a Screen in a .kv file. Keep getting a KeyError: 'container' and AttributeError: 'super' object has no attribute '__getattr__ error. I've looked through the docs and multiple sites and everyone seems to be using some variant of the example found in the docs, which starts the component in the build method.
What I'm trying to say is if this works
class Example(MDApp):
def build(self):
screen = Screen()
data_tables = MDDataTable(
size_hint=(0.9, 0.6),
column_data=[
('Template Id', dp(30)),
('Name', dp(30))
],
row_data=[
('23lkjk33', 'Ayang Paul'),
('28ij399kk', 'Ringwa Justin')
]
)
screen.add_widget(data_tables)
return screen
Example().run()
then why doesn't this work
KV = '''
Screen:
MDDataTable:
size_hint: 0.9, 0.6
pos_hint: {"center_x": 0.5, "center_y": 0.5}
column_data: [('Template Id', dp(30)), ('Name', dp(30))]
row_data: [('23lkjk33', 'Ayang Paul'), ('28ij399kk', 'Ringwa Justin')]
'''
class Example(MDApp):
def build(self):
return Builder.load_string(KV)
Example().run()
???
The problem is that the MDDataTable__init__() method references ids, but when used in a kv file, the ids are not yet available. The MDDataTable is a subclass of ModalView, so it is apparently intended to be used like a Popup rather than in a kv file.
Here is a hack that will let it work in a kv file:
from kivymd.uix.datatables import MDDataTable, TableHeader, TableData, TablePagination
from kivymd.uix.dialog import BaseDialog
class MyDataTable(MDDataTable):
def __init__(self, **kwargs):
# skip the MDDataTable.__init__() and call its superclass __init__()
super(BaseDialog, self).__init__(**kwargs)
# schedule call to MDDataTable.__init__() contents after ids are populated
Clock.schedule_once(partial(self.delayed_init, **kwargs))
def delayed_init(self, dt, **kwargs):
# this is copied from MDDataTable.__init__() with super() call deleted
self.register_event_type("on_row_press")
self.register_event_type("on_check_press")
self.header = TableHeader(column_data=self.column_data, sort=self.sort)
self.table_data = TableData(
self.header,
row_data=self.row_data,
check=self.check,
rows_num=self.rows_num,
_parent=self,
)
self.pagination = TablePagination(table_data=self.table_data)
self.table_data.pagination = self.pagination
self.header.table_data = self.table_data
self.table_data.fbind("scroll_x", self._scroll_with_header)
self.ids.container.add_widget(self.header)
self.ids.container.add_widget(self.table_data)
if self.use_pagination:
self.ids.container.add_widget(self.pagination)
Clock.schedule_once(self.create_pagination_menu, 0.5)
So use MyDataTable in your kv in place of MDDataTable. The above code delays the execution of the guts of the MDDataTable.__init__() method until the ids are available. If the MDDataTable code is ever updated, this hack may not work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With