AWTK 表格视图的实现原理和用法

ops/2025/1/15 18:08:42/

表格视图的基本用法

1. 基本概念

在这里插入图片描述

  • table_view_t 是表格视图的外壳,它的主要功能是协调 table_client_t 和滚动条。

  • table_header_t 是表格的标题,它其实只是一个普通的容器,完全可以用 view 代替,但用 table_header_t 更具可读性。

  • table_client_t 是表格的数据区,它是一个 table_row_t 的容器。

  • table_row_t 表示表格中的一行,它只是个容器,里面可以文本、图片、编辑器、进度条、滑块和下拉框等各种控件。

在这里插入图片描述

table_view_t 的为了解决大量数据的问题,我们把数据分为三类:

  • 虚拟区域。代表全部数据,它是虚拟的,无需加入到内存中来。

  • 缓存区域。代表实际在内存中创建的部分,为了让滑动效果比较流畅,缓存区域是可视区域的 3 倍。

  • 可视区域。代表当前呈现在窗口上的部分。

在这里插入图片描述

当拖到滚动条改变可视区域时,如果可视区域超出缓存区域,则调用用户提供的回调函数,更新缓存区域的位置和数据。

2. 用法

2.1 编写 XML

table_view 由 table_header(可选)、table_client 和 scroll_bar 组成。

在 table_client 中,只需要写一个 table_row,这个 table_row 只是作为模版,由 table_client 根据需要创建。

示例:

  <table_view x="10" y="10" w="-20" h="-80"><table_header x="0"  y="0" w="-12" h="30" name="title" children_layout="default(r=1,c=0,s=5,m=5)"><label w="20%" text="Name" /><label w="20%" text="Color"/><label w="40%" text="Value" /><label w="20%" text="Action" /></table_header><table_client name="table_client" x="0"  y="30" w="-12" h="-30" row_height="40"><table_row children_layout="default(r=1,c=0,s=5,m=5)"><label name="name"  w="20%" h="100%" text="name" /><combo_box name="color" readonly="true" w="20%" h="80%" options="red;green;blue"/><slider name="value" w="40%" h="80%" /><button name="remove" w="20%" h="80%" text="Remove" /></table_row></table_client><scroll_bar_d name="vbar" x="right" y="0" w="12" h="100%" value="0"/></table_view>

2.1 编写准备数据的回调函数

table_client 不需要预先创建全部的 table_row,而是在需要时调用回调函数,去填充指定行的数据。以当前的行号和 table_row 对象为参数,实现者在回调函数中,加载当前行的数据,然后设置到 row 的子控件中。

/*** @method table_client_set_on_load_data* 设置 加载数据的回调函数。* @param {widget_t*} widget widget 对象。* @param {table_client_on_load_data_t} on_load_data 回调函数。* @param {void*} ctx 回调函数的上下文。 ** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t table_client_set_on_load_data(widget_t* widget, table_client_on_load_data_t on_load_data,void* ctx);

示例:

static ret_t on_load_data(void* ctx, uint32_t index, widget_t* row) {char name[32];tk_snprintf(name, sizeof(name), "name:%u", index);widget_set_text_utf8(widget_lookup(row, "name", TRUE), name);widget_set_value(widget_lookup(row, "value", TRUE),index%100);widget_set_value(widget_lookup(row, "color", TRUE), 0);return RET_OK;
}...table_client_set_on_load_data(client, on_load_data, client);
...

在本回调函数中,还可以调整控件的大小,设置控件的 style。

2.2 编写注册事件的回调函数

有时候,我们不是简单的显示数据,还要对数据进行编辑。此时需要设置一个回调函数,这个回调函数在 table_row 创建完成后调用。


/*** @method table_client_set_on_create_row* 设置 创建行时的回调函数,在回调函数中可以注册控件的事件。* @param {widget_t*} widget widget 对象。* @param {table_client_on_create_row_t} on_create_row 回调函数,在回调函数加载数据。* @param {void*} ctx 回调函数的上下文。 ** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t table_client_set_on_create_row(widget_t* widget, table_client_on_create_row_t on_create_row,void* ctx)

示例:

static table_row_t* table_row_of(widget_t* child) {widget_t* iter = child;while(iter != NULL && !tk_str_eq(widget_get_type(iter), WIDGET_TYPE_TABLE_ROW)) {iter = iter->parent;}return TABLE_ROW(iter);
}static ret_t on_value_changed(void* ctx, event_t* e) {table_row_t* row = table_row_of(WIDGET(e->target));log_debug("changed: %d value=%d\n", row->index, widget_get_value(WIDGET(e->target)));return RET_OK;
}static ret_t on_color_changed(void* ctx, event_t* e) {table_row_t* row = table_row_of(WIDGET(e->target));log_debug("changed: %d value=%s\n", row->index, combo_box_get_text(WIDGET(e->target)));return RET_OK;
}static ret_t on_remove_clicked(void* ctx, event_t* e) {table_row_t* row = table_row_of(WIDGET(e->target));log_debug("clicked: %d \n", row->index);return RET_OK;
}static ret_t on_create_row(void* ctx, uint32_t index, widget_t* row) {widget_child_on(row, "value", EVT_VALUE_CHANGED, on_value_changed, NULL);widget_child_on(row, "color", EVT_VALUE_CHANGED, on_color_changed, NULL);widget_child_on(row, "remove", EVT_CLICK, on_remove_clicked, NULL);return RET_OK;
}...table_client_set_on_create_row(client, on_create_row, client);

在控件的事件处理函数中,可以通过 table_row_of 获取 row 对象,然后通过 row 对象的 index 属性,获取当前的行号,然后将数据保存到当前的行(如数据库)。


http://www.ppmy.cn/ops/13232.html

相关文章

使用Spring进行文件的上传和下载

概览 使用Spring进行文件的上传和下载Spring上传文件接口设计dubbo接口设计上传文件流的RPC的接口设计 Spring文件下载接口设计dubbo接口设计下载文件流的RPC的接口设计 spring上传文件大小控制 使用Spring进行文件的上传和下载 本文主要介绍在Spring框架下面调用微服务的dubb…

什么是国内生产总值(GDP)

国内生产总值 , 是国际上通行的用于衡量一个国家&#xff08;或地区&#xff09;经济运行规模的宏观经济指标&#xff0c;其在政治、经济、外交、研究等领域具有广泛应用。 一、国内生产总值的基本概念 国内生产总值是指一个国家和地区所有常住单位在一定时期内生产活动的全部…

NAT的知识点和实现

1.NAT的作用&#xff1a; &#xff08;1&#xff09;、把内网私网IP转换公网IP&#xff1b; &#xff08;2&#xff09;、隐藏内网&#xff0c;起到保护内网作用&#xff1b; &#xff08;3&#xff09;、适当的缓解的IPv4地址空间枯竭&#xff1b; &#xff08;4&#xff…

面试经典150题——二叉树展开为链表

​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 因为题目中提到&#xff1a;展开后的单链表应该与二叉树 先序遍历 顺序相同&#xff0c;那么我们是不是就可以先先序遍历&#xff0c;然后按照先序遍历的节点一个一个赋值&#xff1f; 其实最简单的思路就是用一个结构按顺序存…

MySQL-锁篇

文章目录 表级锁和行级锁了解吗&#xff1f;有什么区别&#xff1f;行级锁使用有什么注意事项&#xff1f;InnoDB有哪几类行锁&#xff1f;共享锁和排他锁是什么&#xff1f;意向锁有什么用&#xff1f; 锁是一种常见的并发事务的控制方式 表级锁和行级锁了解吗&#xff1f;有什…

云计算时代,企业面临的云安全风险

如今&#xff0c;随着云计算等新兴科技的发展&#xff0c;不同类型企业间的关联越来越多&#xff0c;它们之间的业务边界已被打破&#xff0c;企业上云成为了大势所趋。云计算应用帮助企业改变了IT资源不集中的状况&#xff0c;同时&#xff0c;数据中心内存储的大量数据信息&a…

uniapp制作多选下拉框和富文本(短信页面)

实例 多选下拉框实现 http://t.csdnimg.cn/TNmcF 富文本实现 http://t.csdnimg.cn/Ei1iV

面试经典150题——分发糖果

面试经典150题 day15 题目来源我的题解方法一 两次不同方向的遍历&#xff08;应该是贪心&#xff09;方法二 贪心 题目来源 力扣每日一题&#xff1b;题序&#xff1a;135 我的题解 方法一 两次不同方向的遍历&#xff08;应该是贪心&#xff09; 遍历两次&#xff08;左→…