Table (lv_table)¶
Overview¶
Tables, as usual, are built from rows, columns, and cells containing texts.
The Table object is very lightweight because only the texts are stored. No real objects are created for cells but they are just drawn on the fly.
The Table is added to the default group (if it is set). Besides the Table is an editable object to allow selecting a cell with encoder navigation too.
Parts and Styles¶
LV_PART_MAIN
The background of the table uses all the typical background style properties.LV_PART_ITEMS
The cells of the table also use all the typical background style properties and the text properties.
Usage¶
Set cell value¶
The cells can store only text so numbers need to be converted to text before displaying them in a table.
lv_table_set_cell_value(table, row, col, "Content")
. The text is saved by the table so it can be even a local variable.
Line breaks can be used in the text like "Value\n60.3"
.
New rows and columns are automatically added is required
Rows and Columns¶
To explicitly set number of rows and columns use lv_table_set_row_cnt(table, row_cnt)
and lv_table_set_col_cnt(table, col_cnt)
Width and Height¶
The width of the columns can be set with lv_table_set_col_width(table, col_id, width)
. The overall width of the Table object will be set to the sum of columns widths.
The height is calculated automatically from the cell styles (font, padding etc) and the number of rows.
Merge cells¶
Cells can be merged horizontally with lv_table_add_cell_ctrl(table, row, col, LV_TABLE_CELL_CTRL_MERGE_RIGHT)
. To merge more adjacent cells call this function for each cell.
Scroll¶
If the label's width or height is set to LV_SIZE_CONTENT
that size will be used to show the whole table in the respective direction.
E.g. lv_obj_set_size(table, LV_SIZE_CONTENT, LV_SIZE_CONTENT)
automatically sets the table size to show all the columns and rows.
If the width or height is set to a smaller number than the "intrinsic" size then the table becomes scrollable.
Events¶
LV_EVENT_VALUE_CHANGED
Sent when a new cell is selected with keys.LV_EVENT_DRAW_PART_BEGIN
andLV_EVENT_DRAW_PART_END
are sent for the following types:LV_TABLE_DRAW_PART_CELL
The individual cells of the tablepart
:LV_PART_ITEMS
draw_area
: area of the indicatorrect_dsc
label_dsc
id
: current row × col count + current column
See the events of the Base object too.
Learn more about Events.
Keys¶
The following Keys are processed by the Tables:
LV_KEY_RIGHT/LEFT/UP/DOWN/
Select a cell.
Note that, as usual, the state of LV_KEY_ENTER
is translated to LV_EVENT_PRESSED/PRESSING/RELEASED
etc.
lv_table_get_selected_cell(table, &row, &col)
can be used to get the currently selected cell. Row and column will be set to LV_TABLE_CELL_NONE
no cell is selected.
Learn more about Keys.
Example¶
Simple table¶
C code
GitHub#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_BUILD_EXAMPLES
static void draw_part_event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e);
/*If the cells are drawn...*/
if(dsc->part == LV_PART_ITEMS) {
uint32_t row = dsc->id / lv_table_get_col_cnt(obj);
uint32_t col = dsc->id - row * lv_table_get_col_cnt(obj);
/*Make the texts in the first cell center aligned*/
if(row == 0) {
dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
dsc->rect_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_BLUE), dsc->rect_dsc->bg_color, LV_OPA_20);
dsc->rect_dsc->bg_opa = LV_OPA_COVER;
}
/*In the first column align the texts to the right*/
else if(col == 0) {
dsc->label_dsc->align = LV_TEXT_ALIGN_RIGHT;
}
/*MAke every 2nd row grayish*/
if((row != 0 && row % 2) == 0) {
dsc->rect_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_GREY), dsc->rect_dsc->bg_color, LV_OPA_10);
dsc->rect_dsc->bg_opa = LV_OPA_COVER;
}
}
}
void lv_example_table_1(void)
{
lv_obj_t * table = lv_table_create(lv_scr_act());
/*Fill the first column*/
lv_table_set_cell_value(table, 0, 0, "Name");
lv_table_set_cell_value(table, 1, 0, "Apple");
lv_table_set_cell_value(table, 2, 0, "Banana");
lv_table_set_cell_value(table, 3, 0, "Lemon");
lv_table_set_cell_value(table, 4, 0, "Grape");
lv_table_set_cell_value(table, 5, 0, "Melon");
lv_table_set_cell_value(table, 6, 0, "Peach");
lv_table_set_cell_value(table, 7, 0, "Nuts");
/*Fill the second column*/
lv_table_set_cell_value(table, 0, 1, "Price");
lv_table_set_cell_value(table, 1, 1, "$7");
lv_table_set_cell_value(table, 2, 1, "$4");
lv_table_set_cell_value(table, 3, 1, "$6");
lv_table_set_cell_value(table, 4, 1, "$2");
lv_table_set_cell_value(table, 5, 1, "$5");
lv_table_set_cell_value(table, 6, 1, "$1");
lv_table_set_cell_value(table, 7, 1, "$9");
/*Set a smaller height to the table. It'll make it scrollable*/
lv_obj_set_height(table, 200);
lv_obj_center(table);
/*Add an event callback to to apply some custom drawing*/
lv_obj_add_event_cb(table, draw_part_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
}
#endif
def draw_part_event_cb(e):
obj = e.get_target()
dsc = lv.obj_draw_part_dsc_t.__cast__(e.get_param())
# If the cells are drawn../
if dsc.part == lv.PART.ITEMS:
row = dsc.id // obj.get_col_cnt()
col = dsc.id - row * obj.get_col_cnt()
# Make the texts in the first cell center aligned
if row == 0:
dsc.label_dsc.align = lv.TEXT_ALIGN.CENTER
dsc.rect_dsc.bg_color = lv.palette_main(lv.PALETTE.BLUE).color_mix(dsc.rect_dsc.bg_color, lv.OPA._20)
dsc.rect_dsc.bg_opa = lv.OPA.COVER
# In the first column align the texts to the right
elif col == 0:
dsc.label_dsc.flag = lv.TEXT_ALIGN.RIGHT
# Make every 2nd row grayish
if row != 0 and (row % 2) == 0:
dsc.rect_dsc.bg_color = lv.palette_main(lv.PALETTE.GREY).color_mix(dsc.rect_dsc.bg_color, lv.OPA._10)
dsc.rect_dsc.bg_opa = lv.OPA.COVER
table = lv.table(lv.scr_act())
# Fill the first column
table.set_cell_value(0, 0, "Name")
table.set_cell_value(1, 0, "Apple")
table.set_cell_value(2, 0, "Banana")
table.set_cell_value(3, 0, "Lemon")
table.set_cell_value(4, 0, "Grape")
table.set_cell_value(5, 0, "Melon")
table.set_cell_value(6, 0, "Peach")
table.set_cell_value(7, 0, "Nuts")
# Fill the second column
table.set_cell_value(0, 1, "Price")
table.set_cell_value(1, 1, "$7")
table.set_cell_value(2, 1, "$4")
table.set_cell_value(3, 1, "$6")
table.set_cell_value(4, 1, "$2")
table.set_cell_value(5, 1, "$5")
table.set_cell_value(6, 1, "$1")
table.set_cell_value(7, 1, "$9")
# Set a smaller height to the table. It'll make it scrollable
table.set_height(200)
table.center()
# Add an event callback to apply some custom drawing
table.add_event_cb(draw_part_event_cb, lv.EVENT.DRAW_PART_BEGIN, None)
Lightweighted list from table¶
C code
GitHub#include "../../lv_examples.h"
#if LV_USE_TABLE && LV_BUILD_EXAMPLES
#define ITEM_CNT 200
static void draw_event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e);
/*If the cells are drawn...*/
if(dsc->part == LV_PART_ITEMS) {
bool chk = lv_table_has_cell_ctrl(obj, dsc->id, 0, LV_TABLE_CELL_CTRL_CUSTOM_1);
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = chk ? lv_theme_get_color_primary(obj) : lv_palette_lighten(LV_PALETTE_GREY, 2);
rect_dsc.radius = LV_RADIUS_CIRCLE;
lv_area_t sw_area;
sw_area.x1 = dsc->draw_area->x2 - 50;
sw_area.x2 = sw_area.x1 + 40;
sw_area.y1 = dsc->draw_area->y1 + lv_area_get_height(dsc->draw_area) / 2 - 10;
sw_area.y2 = sw_area.y1 + 20;
lv_draw_rect(dsc->draw_ctx, &rect_dsc, &sw_area);
rect_dsc.bg_color = lv_color_white();
if(chk) {
sw_area.x2 -= 2;
sw_area.x1 = sw_area.x2 - 16;
}
else {
sw_area.x1 += 2;
sw_area.x2 = sw_area.x1 + 16;
}
sw_area.y1 += 2;
sw_area.y2 -= 2;
lv_draw_rect(dsc->draw_ctx, &rect_dsc, &sw_area);
}
}
static void change_event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
uint16_t col;
uint16_t row;
lv_table_get_selected_cell(obj, &row, &col);
bool chk = lv_table_has_cell_ctrl(obj, row, 0, LV_TABLE_CELL_CTRL_CUSTOM_1);
if(chk) lv_table_clear_cell_ctrl(obj, row, 0, LV_TABLE_CELL_CTRL_CUSTOM_1);
else lv_table_add_cell_ctrl(obj, row, 0, LV_TABLE_CELL_CTRL_CUSTOM_1);
}
/**
* A very light-weighted list created from table
*/
void lv_example_table_2(void)
{
/*Measure memory usage*/
lv_mem_monitor_t mon1;
lv_mem_monitor(&mon1);
uint32_t t = lv_tick_get();
lv_obj_t * table = lv_table_create(lv_scr_act());
/*Set a smaller height to the table. It'll make it scrollable*/
lv_obj_set_size(table, LV_SIZE_CONTENT, 200);
lv_table_set_col_width(table, 0, 150);
lv_table_set_row_cnt(table, ITEM_CNT); /*Not required but avoids a lot of memory reallocation lv_table_set_set_value*/
lv_table_set_col_cnt(table, 1);
/*Don't make the cell pressed, we will draw something different in the event*/
lv_obj_remove_style(table, NULL, LV_PART_ITEMS | LV_STATE_PRESSED);
uint32_t i;
for(i = 0; i < ITEM_CNT; i++) {
lv_table_set_cell_value_fmt(table, i, 0, "Item %"LV_PRIu32, i + 1);
}
lv_obj_align(table, LV_ALIGN_CENTER, 0, -20);
/*Add an event callback to to apply some custom drawing*/
lv_obj_add_event_cb(table, draw_event_cb, LV_EVENT_DRAW_PART_END, NULL);
lv_obj_add_event_cb(table, change_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
lv_mem_monitor_t mon2;
lv_mem_monitor(&mon2);
uint32_t mem_used = mon1.free_size - mon2.free_size;
uint32_t elaps = lv_tick_elaps(t);
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text_fmt(label, "%"LV_PRIu32" items were created in %"LV_PRIu32" ms\n"
"using %"LV_PRIu32" bytes of memory",
ITEM_CNT, elaps, mem_used);
lv_obj_align(label, LV_ALIGN_BOTTOM_MID, 0, -10);
}
#endif
from utime import ticks_ms
import gc
ITEM_CNT = 200
def draw_event_cb(e):
obj = e.get_target()
dsc = lv.obj_draw_part_dsc_t.__cast__(e.get_param())
# If the cells are drawn...
if dsc.part == lv.PART.ITEMS:
chk = obj.has_cell_ctrl(dsc.id, 0, lv.table.CELL_CTRL.CUSTOM_1)
rect_dsc = lv.draw_rect_dsc_t()
rect_dsc.init()
if chk:
rect_dsc.bg_color = lv.theme_get_color_primary(obj)
else:
rect_dsc.bg_color = lv.palette_lighten(lv.PALETTE.GREY, 2)
rect_dsc.radius = lv.RADIUS.CIRCLE
sw_area = lv.area_t()
sw_area.x1 = dsc.draw_area.x2 - 50
sw_area.x2 = sw_area.x1 + 40
sw_area.y1 = dsc.draw_area.y1 + dsc.draw_area.get_height() // 2 - 10
sw_area.y2 = sw_area.y1 + 20
dsc.draw_ctx.rect(rect_dsc, sw_area)
rect_dsc.bg_color = lv.color_white()
if chk:
sw_area.x2 -= 2
sw_area.x1 = sw_area.x2 - 16
else:
sw_area.x1 += 2
sw_area.x2 = sw_area.x1 + 16
sw_area.y1 += 2
sw_area.y2 -= 2
dsc.draw_ctx.rect(rect_dsc, sw_area)
def change_event_cb(e):
obj = e.get_target()
row = lv.C_Pointer()
col = lv.C_Pointer()
table.get_selected_cell(row, col)
# print("row: ",row.uint_val)
chk = table.has_cell_ctrl(row.uint_val, 0, lv.table.CELL_CTRL.CUSTOM_1)
if chk:
table.clear_cell_ctrl(row.uint_val, 0, lv.table.CELL_CTRL.CUSTOM_1)
else:
table.add_cell_ctrl(row.uint_val, 0, lv.table.CELL_CTRL.CUSTOM_1)
#
# A very light-weighted list created from table
#
# Measure memory usage
gc.enable()
gc.collect()
mem_free = gc.mem_free()
print("mem_free: ", mem_free)
t = ticks_ms()
print("ticks: ", t)
table = lv.table(lv.scr_act())
# Set a smaller height to the table. It'll make it scrollable
table.set_size(150, 200)
table.set_col_width(0, 150)
table.set_row_cnt(ITEM_CNT) # Not required but avoids a lot of memory reallocation lv_table_set_set_value
table.set_col_cnt(1)
# Don't make the cell pressed, we will draw something different in the event
table.remove_style(None, lv.PART.ITEMS | lv.STATE.PRESSED)
for i in range(ITEM_CNT):
table.set_cell_value(i, 0, "Item " + str(i+1))
table.align(lv.ALIGN.CENTER, 0, -20)
# Add an event callback to apply some custom drawing
table.add_event_cb(draw_event_cb, lv.EVENT.DRAW_PART_END, None)
table.add_event_cb(change_event_cb, lv.EVENT.VALUE_CHANGED, None)
gc.collect()
mem_used = mem_free - gc.mem_free()
elaps = ticks_ms()-t
label = lv.label(lv.scr_act())
label.set_text(str(ITEM_CNT) + " items were created in " + str(elaps) + " ms\n using " + str(mem_used) + " bytes of memory")
#label.set_text(str(ITEM_CNT) + " items were created in " + str(elaps) + " ms")
label.align(lv.ALIGN.BOTTOM_MID, 0, -10)
MicroPython¶
No examples yet.
API¶
Typedefs
-
typedef uint8_t lv_table_cell_ctrl_t¶
Enums
Functions
-
LV_EXPORT_CONST_INT(LV_TABLE_CELL_NONE)¶
-
lv_obj_t *lv_table_create(lv_obj_t *parent)¶
Create a table object
- Parameters
parent -- pointer to an object, it will be the parent of the new table
- Returns
pointer to the created table
-
void lv_table_set_cell_value(lv_obj_t *obj, uint16_t row, uint16_t col, const char *txt)¶
Set the value of a cell.
Note
New roes/columns are added automatically if required
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
txt -- text to display in the cell. It will be copied and saved so this variable is not required after this function call.
-
void lv_table_set_cell_value_fmt(lv_obj_t *obj, uint16_t row, uint16_t col, const char *fmt, ...)¶
Set the value of a cell. Memory will be allocated to store the text by the table.
Note
New roes/columns are added automatically if required
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
fmt --
printf
-like format
-
void lv_table_set_row_cnt(lv_obj_t *obj, uint16_t row_cnt)¶
Set the number of rows
- Parameters
obj -- table pointer to a Table object
row_cnt -- number of rows
-
void lv_table_set_col_cnt(lv_obj_t *obj, uint16_t col_cnt)¶
Set the number of columns
- Parameters
obj -- table pointer to a Table object
col_cnt -- number of columns.
-
void lv_table_set_col_width(lv_obj_t *obj, uint16_t col_id, lv_coord_t w)¶
Set the width of a column
- Parameters
obj -- table pointer to a Table object
col_id -- id of the column [0 .. LV_TABLE_COL_MAX -1]
w -- width of the column
-
void lv_table_add_cell_ctrl(lv_obj_t *obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl)¶
Add control bits to the cell.
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
ctrl -- OR-ed values from ::lv_table_cell_ctrl_t
-
void lv_table_clear_cell_ctrl(lv_obj_t *obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl)¶
Clear control bits of the cell.
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
ctrl -- OR-ed values from ::lv_table_cell_ctrl_t
-
void lv_table_set_cell_user_data(lv_obj_t *obj, uint16_t row, uint16_t col, void *user_data)¶
Add custom user data to the cell.
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
user_data -- pointer to the new user_data. It must be allocated by user as it will be freed automatically
-
const char *lv_table_get_cell_value(lv_obj_t *obj, uint16_t row, uint16_t col)¶
Get the value of a cell.
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
- Returns
text in the cell
-
uint16_t lv_table_get_row_cnt(lv_obj_t *obj)¶
Get the number of rows.
- Parameters
obj -- table pointer to a Table object
- Returns
number of rows.
-
uint16_t lv_table_get_col_cnt(lv_obj_t *obj)¶
Get the number of columns.
- Parameters
obj -- table pointer to a Table object
- Returns
number of columns.
-
lv_coord_t lv_table_get_col_width(lv_obj_t *obj, uint16_t col)¶
Get the width of a column
- Parameters
obj -- table pointer to a Table object
col -- id of the column [0 .. LV_TABLE_COL_MAX -1]
- Returns
width of the column
-
bool lv_table_has_cell_ctrl(lv_obj_t *obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl)¶
Get whether a cell has the control bits
- Parameters
obj -- pointer to a Table object
row -- id of the row [0 .. row_cnt -1]
col -- id of the column [0 .. col_cnt -1]
ctrl -- OR-ed values from ::lv_table_cell_ctrl_t
- Returns
true: all control bits are set; false: not all control bits are set
-
void lv_table_get_selected_cell(lv_obj_t *obj, uint16_t *row, uint16_t *col)¶
Get the selected cell (pressed and or focused)
- Parameters
obj -- pointer to a table object
row -- pointer to variable to store the selected row (LV_TABLE_CELL_NONE: if no cell selected)
col -- pointer to variable to store the selected column (LV_TABLE_CELL_NONE: if no cell selected)
Variables
-
const lv_obj_class_t lv_table_class¶
-
struct lv_table_cell_t¶
-
struct lv_table_t¶