Skip to content

Instantly share code, notes, and snippets.

@Eitol
Last active January 29, 2024 20:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Eitol/968d8212be3be5a4a3952ca73203da70 to your computer and use it in GitHub Desktop.
Save Eitol/968d8212be3be5a4a3952ca73203da70 to your computer and use it in GitHub Desktop.
Simple Data grid for kivy. (Work in python 3 an 2)
import json
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.label import Label
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from functools import partial
Builder.load_string('''
# define how clabel looks and behaves
<CLabel>:
canvas.before:
Color:
rgb: self.bgcolor
Rectangle:
size: self.size
pos: self.pos
<HeaderLabel>:
canvas.before:
Color:
rgb: self.bgcolor
Rectangle:
size: self.size
pos: self.pos
'''
)
class CLabel(ToggleButton):
bgcolor = ListProperty()
class HeaderLabel(Label):
bgcolor = ListProperty()
class DataGrid(GridLayout):
def __init__(self, header_data, cols_size, **kwargs):
super(DataGrid, self).__init__(**kwargs)
self.rows = 0
self.size_hint_y = None
self.bind(minimum_height=self.setter('height'))
self.cols = len(header_data)
self.spacing = [1, 1]
self.counter = 0
n = 0
for hcell in header_data:
header_str = "[b]" + str(hcell) + "[/b]"
self.add_widget(HeaderLabel(text=header_str, markup=True, size_hint_y=None,
height=40, id="Header_Label", size_hint_x=cols_size[n],
bgcolor=[0.108, 0.476, 0.611]))
n += 1
def add_row(self, row_data, row_align, cols_size):
self.rows += 1
def change_on_press(clabel):
childs = clabel.parent.children
for ch in childs:
if ch.id == clabel.id:
row_n = ch.id[4:5] if len(ch.id) == 11 else ch.id[4:6]
for c in childs:
if ('row_' + str(row_n) + '_col_') in c.id:
change_on_release(c)
def change_on_release(clabel):
clabel.state = "down" if clabel.state == "normal" else "normal"
n = 0
for item in row_data:
cell = CLabel(text=('[color=000000]' + item + '[/color]'),
# background_color_normal=ListProperty([1, 1, 1, 0.5]),
# background_color_down = ListProperty([1, 1, 1, 1])
background_normal="background_normal.png",
background_down="background_pressed.png",
bgcolor=[1, 1, 1],
halign=row_align[n],
markup=True,
on_press=partial(change_on_press),
on_release=partial(change_on_release),
text_size=(0, None),
size_hint_x=cols_size[n],
size_hint_y=None,
height=40,
id=("row_" + str(self.counter) + "_col_" + str(n)))
cell_width = Window.size[0] * cell.size_hint_x
cell.text_size = (cell_width - 30, None)
cell.texture_update()
self.add_widget(cell)
n += 1
self.counter += 1
# self.rows += 1
def remove_row(self, n_cols, instance, **kwargs):
childs = self.parent.children
selected = 0
for ch in childs:
for c in reversed(ch.children):
if c.id != "Header_Label":
if c.state == "down":
self.remove_widget(c)
selected += 1
if selected == 0:
for ch in childs:
count = 0
while count < n_cols:
if n_cols != len(ch.children):
for c in ch.children:
if c.id != "Header_Label":
self.remove_widget(c)
count += 1
break
else:
break
else:
break
def select_all(self, instance, **kwargs):
self.change_state("down")
def unselect_all(self, instance, **kwargs):
self.change_state("normal")
def change_state(self, state):
childs = self.parent.children
for ch in childs:
for c in ch.children:
if c.id != "Header_Label":
c.state = state
class Table(BoxLayout):
def __init__(self, header, **kwargs):
super(Table, self).__init__(orientation="horizontal")
self.col_size = [0.1, 0.5, 0.2, 0.2]
# header = ['ID', 'Nome', 'Preco', 'IVA']
self.grid = DataGrid(header, self.col_size)
self.grid.rows = 1
scroll = ScrollView(size_hint=(1, 1), size=(400, 500000), scroll_y=0, pos_hint={'center_x': .5, 'center_y': .5})
scroll.add_widget(self.grid)
scroll.do_scroll_x, scroll.do_scroll_y = False, True
self.add_widget(scroll)
data_json = open('data.json')
data = json.load(data_json)
self.fill(data)
def fill(self, data):
body_alignment = ["center", "center", "center", "center"]
for d in data:
self.grid.add_row(d, body_alignment, self.col_size)
class MainApp(App):
def build(self):
return Table(['ID', 'Nome', 'Preco', 'IVA'])
if __name__ == '__main__':
MainApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment