-
-
Save sirpercival/4acce2375a22b6ea724e to your computer and use it in GitHub Desktop.
| from kivy.lang import Builder | |
| from kivy.uix.gridlayout import GridLayout | |
| from kivy.properties import DictProperty, NumericProperty, StringProperty, \ | |
| BooleanProperty, ObjectProperty | |
| from operator import itemgetter | |
| from kivy.uix.button import Button | |
| from kivy.uix.textinput import TextInput | |
| from kivy.uix.label import Label | |
| Builder.load_string(""" | |
| <ColHeader>: | |
| bold: True | |
| on_press: self.data_table.sort_by(self.text) | |
| <RowHeader>: | |
| background_down: self.background_normal | |
| <EditableCell>: | |
| multiline: False | |
| on_focus: if not self.focus: self.data_table.data_update(self.id, self.text) | |
| <StaticCell>: | |
| halign: 'left' | |
| <DataTable>: | |
| id: table_grid | |
| cols: self.ncol | |
| """) | |
| class ColHeader(Button): | |
| #For some reason, adding this property as part of a | |
| #dynamic class declaration was failing. | |
| data_table = ObjectProperty(None) | |
| class RowHeader(Button): | |
| data_table = ObjectProperty(None) | |
| initial_type = ObjectProperty(None) | |
| class EditableCell(TextInput): | |
| data_table = ObjectProperty(None) | |
| initial_type = ObjectProperty(None) | |
| class StaticCell(Label): | |
| data_table = ObjectProperty(None) | |
| initial_type = ObjectProperty(None) | |
| class DataTable(GridLayout): | |
| """This is a compound widget designed to display | |
| a dictionary of data as a nice table. The dictionary | |
| should have the column headers as keys, and then | |
| the associated value is a list of data for that | |
| column. | |
| You may have lists of different lengths, but the columns | |
| will fill from the top down; therefore, include blank | |
| strings as placeholders for any empty cells. | |
| Note that since the column headers are dict keys, you | |
| must have unique column names. Sorry...""" | |
| data = DictProperty({}) | |
| ncol = NumericProperty(0) | |
| nrow = NumericProperty(0) | |
| editable = BooleanProperty(False) | |
| header_col = StringProperty('') | |
| def __init__(self, data = {}, editable = False, header_column = '', | |
| header_row = [], **kw): | |
| super(DataTable, self).__init__(**kw) | |
| self.data = data | |
| self.ncol = len(data) | |
| self.editable = editable | |
| self.header_col = header_column | |
| self.header_row = header_row | |
| celltype = EditableCell if self.editable else StaticCell | |
| self.nrow = max([len(data[x]) for x in data]) | |
| self.cells = {} | |
| for key in self.header_row: | |
| cell_id = str(key)+'_head' | |
| cell = ColHeader(text = str(key), data_table = self, id = cell_id) | |
| self.cells[cell_id] = cell | |
| self.add_widget(cell) | |
| for i in xrange(self.nrow): | |
| get = itemgetter(i) | |
| for key in self.header_row: | |
| cell_id = str(key)+'_'+str(i) | |
| if i <= len(self.data[key]): | |
| text = get(self.data[key]) | |
| else: | |
| text = '' | |
| self.data[key].append('') | |
| if key == self.header_col: | |
| self.cells[cell_id] = RowHeader(text = str(text), data_table = self, | |
| id = cell_id, initial_type = type(text)) | |
| else: | |
| self.cells[cell_id] = celltype(text = str(text), data_table = self, | |
| id = cell_id, initial_type = type(text)) | |
| self.add_widget(self.cells[cell_id]) | |
| def data_update(self, cell_id, value): | |
| """This will try to convert the value | |
| to the initial type of the data. If that fails, | |
| it'll just be a string. The initial type won't | |
| change, however.""" | |
| key, idx = cell_id.split('_') | |
| try: | |
| val = self.cells[cell_id].initial_type(value) | |
| except ValueError: | |
| val = value | |
| self.data[key][int(idx)] = val | |
| def sort_by(self, colname): | |
| column_to_order = enumerate(self.data[colname]) | |
| sort_order = map(itemgetter(0), | |
| sorted(column_to_order, key=itemgetter(1))) | |
| for key in self.data: | |
| col = self.data[key] | |
| self.data[key] = [col[x] for x in sort_order] | |
| self.cells[str(key)+'_head'].background_color = (1, 1, 1, 1) | |
| for i in xrange(self.nrow): | |
| self.cells[str(key)+'_'+str(i)].text = str(self.data[key][i]) | |
| self.cells[colname+'_head'].background_color = (0, 1, 0, 1) | |
| if __name__ == '__main__': | |
| import random | |
| data = {'Col1':[random.random() for x in xrange(10)], | |
| 'Col2':[random.random() for x in xrange(10)], | |
| 'Col3':[random.random() for x in xrange(10)], | |
| 'Col4':[random.random() for x in xrange(10)], | |
| 'Col5':[random.random() for x in xrange(10)]} | |
| from kivy.base import runTouchApp | |
| from kivy.uix.pagelayout import PageLayout | |
| from kivy.factory import Factory | |
| Builder.load_string(""" | |
| <Page@AnchorLayout>: | |
| canvas.before: | |
| Color: | |
| rgba: 0, 0, 0, 1 | |
| Rectangle: | |
| pos: self.pos | |
| size: self.size | |
| """) | |
| pg = PageLayout() | |
| staticpage = Factory.Page(name='static') | |
| staticpage.add_widget(DataTable(name = 'static', data=data, header_column = 'Col1', | |
| header_row = ['Col'+str(x+1) for x in xrange(5)])) | |
| editpage = Factory.Page(name='edit') | |
| editpage.add_widget(DataTable(name = 'edit', data=data, header_column = 'Col5', | |
| header_row = ['Col'+str(5-x) for x in xrange(5)], | |
| editable = True)) | |
| pg.add_widget(staticpage) | |
| pg.add_widget(editpage) | |
| runTouchApp(pg) |
try changing xrange to just range
When I run it, I am getting the following error: Traceback (most recent call last):
File "/home/gari/Documents/api_02/datatable/datatablegist.py", line 141, in
staticpage = Factory.Page(name='static')
File "/home/gari/kivy_venv/lib/python3.8/site-packages/kivy/uix/anchorlayout.py", line 68, in init
super(AnchorLayout, self).init(**kwargs)
File "/home/gari/kivy_venv/lib/python3.8/site-packages/kivy/uix/layout.py", line 76, in init
super(Layout, self).init(**kwargs)
File "/home/gari/kivy_venv/lib/python3.8/site-packages/kivy/uix/widget.py", line 350, in init
super(Widget, self).init(**kwargs)
File "kivy/_event.pyx", line 245, in kivy._event.EventDispatcher.init
TypeError: object.init() takes exactly one argument (the instance to initialize)
I tried to run your code it gave unresolved reference 'xrange'