【LVGL控件学习】圆弧(lv_arc)
一、零件和样式
LV_PART_MAIN
- 背景弧LV_PART_INDICATOR
- 前景弧LV_PART_KNOB
- 手柄
1. 为圆弧不同部分添加颜色
/**
* 为圆弧添加颜色时,要使用arc_color而不是bg_color
* 为手柄添加颜色使用bg_color
*/
lv_obj_set_style_arc_color(arc, lv_color_hex3(0xddc), LV_PART_MAIN);
lv_obj_set_style_arc_color(arc, lv_color_hex3(0xff0), LV_PART_INDICATOR);
lv_obj_set_style_bg_color(arc, lv_color_hex3(0xf60), LV_PART_KNOB);
2. 移除圆弧的手柄
lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
二、用法
1. 值和范围
lv_arc_set_range(arc, min, max)
- 设置圆弧的范围,默认为1-100
lv_arc_set_value(arc, new_value)
- 设置圆弧的值
lv_obj_t* arc = lv_arc_create(lv_scr_act());
lv_obj_center(arc);
lv_arc_set_range(arc, 0, 100); // 设置圆弧的范围
lv_arc_set_value(arc, 20); // 设置圆弧的值
int val = 20; // 弧当前的值
bool forward = true; // 向前标志位
while (!lv_win32_quit_signal)
{
/* 让弧在20-80之间循环移动 */
lv_arc_set_value(arc, val); // 设置圆弧的值为val
if (forward) {
val++;
} else {
val--;
}
if (val == 80 || val == 20) { // 当值为20或80移动反向
forward = !forward;
}
Sleep(5); // 延时5ms
}
2. 旋转
设置前景弧的角度
lv_arc_set_start_angle(arc, start_angle, end_angle)
- 设置前景弧开始的角度
lv_arc_set_end_angle(arc, start_angle, end_angle)
- 设置前景弧结束的角度
lv_arc_set_angles(arc, start_angle, end_angle)
- 同时设置前景弧开始和结束的角度
设置背景弧的角度
lv_arc_set_bg_start_angle(arc, start_angle, end_angle)
- 设置背景弧开始的角度
lv_arc_set_bg_end_angle(arc, start_angle, end_angle)
- 设置背景弧结束的角度
lv_arc_set_bg_angles(arc, start_angle, end_angle)
- 同时设置背景弧开始和结束的角度
零度位于对象的中间右侧(3 点钟方向),并且度数沿顺时针方向增加。 角度应在 [0;360] 范围内
即0为最右侧,90为下侧,180为左侧,270为上侧,360为右侧终点
前景弧和背景弧需要同时设置且值一致,否则将会出现显示异常!
lv_arc_set_angles(arc, 90, 360); // 设置前景弧角度
lv_arc_set_bg_angles(arc, 90, 360); // 设置背景弧角度
设置0度偏移量(设置起点位置)
lv_arc_set_rotation(arc, deg)
- 设置起点的偏移量
偏移量的取值为正数,若为负数可能将造成显示异常
lv_arc_set_rotation(arc, 90); // 设置起点偏移量 -> 顺时针旋转90度
3. 模式
LV_ARC_MODE_NORMAL
- 指标弧从最小值绘制到当前值。LV_ARC_MODE_REVERSE
-指标弧从最大值到当前值逆时针绘制。LV_ARC_MODE_SYMMETRICAL
-指标弧从中间点绘制到当前值。
模式可以通过lv_arc_set_mode(arc, LV_ARC_MODE_...)
设置
当模式为
LV_ARC_MODE_REVERSE
时,请使用lv_arc_set_value(arc, value)
来设置圆弧的值,若用触摸设置,可能会出现显示异常。可使用
lv_obj_clear_flag(arc, LV_OBJ_FLAG_CLICKABLE)
禁用弧的点击事件
4. 变化率
lv_arc_set_change_rage(arc, rate)
- 设置圆弧的变化速度,单位 度/秒, 默认720度/秒
lv_arc_t * pArc = (lv_arc_t*)arc; // 将lv_obj_t*转型为lv_arc_t*
printf("弧默认的速度: %u 度/秒\n", pArc->chg_rate); // 弧默认的速度: 720 度/秒
lv_arc_set_change_rate(arc, 100); // 改变弧的变化速度为100度/秒
printf("弧改变后的速度速度: %u 度/秒\n", pArc->chg_rate); // 弧改变后的速度速度: 100 度/秒
5. 手动设置
要使圆弧不可调整,请使对象不可点击:
lv_obj_clear_flag(arc, LV_OBJ_FLAG_CLICKABLE); // 使圆弧不可点击
三、事件
LV_EVENT_VALUE_CHANGED
- 按下圆弧或者拖动手柄改变圆弧的值
使用
lv_arc_change_value(arc, value)
不会触发该事件
static void _arc_cb(lv_event_t* e)
{
lv_obj_t* label = (lv_obj_t*)lv_event_get_user_data(e); // 获取传进来的用户数据label
lv_obj_t* arc = lv_event_get_target(e); // 获取触发的控件arc
uint16_t value = lv_arc_get_value(arc); // 获取arc当前的值
lv_label_set_text_fmt(label, "Value: %u", value); // 更新label的显示
return;
}
void lv_arc(void)
{
lv_obj_t* label = lv_label_create(lv_scr_act()); // 创建用于显示当前弧的值的标签
lv_obj_center(label);
lv_label_set_text(label, "Value: 0");
lv_obj_t* arc = lv_arc_create(lv_scr_act()); // 创建圆弧
lv_obj_add_event_cb(arc, _arc_cb, LV_EVENT_VALUE_CHANGED, (void*)label); // 添加回调函数
lv_obj_center(arc);
lv_arc_set_value(arc, 0); // 设置当前值
lv_arc_set_range(arc, 0, 100); // 设置弧的范围
lv_arc_set_change_rate(arc, 200); // 设置弧的速度
return;
}
四、示例
// 屏幕大小 580 * 250
/**
* @brief 动画回调函数
* @param obj 动画处理的对象
* @param v 当前的值
*/
static void _set_angle(void* obj, int32_t v)
{
lv_arc_set_value((lv_obj_t*)obj, v); // 设置圆弧的值
}
/**
* @brief 动画调整圆弧的值
* @param obj 动画要处理的对象
* @param val 要改变到的值
*/
static void _set_var_value_anim(lv_obj_t* obj, int val)
{
lv_anim_t a; // 创建动画
lv_anim_init(&a); // 初始化动画
lv_anim_set_exec_cb(&a, _set_angle); // 设置动画回调函数
uint16_t old = lv_arc_get_value(obj); // 获取圆弧当前值
lv_anim_set_var(&a, obj); // 将圆弧与动画绑定
lv_anim_set_values(&a, old, val); // 设置动画处理值的改变范围
lv_anim_set_time(&a, 1000); // 设置动画持续时间
lv_anim_start(&a); // 开始执行动画
}
void arc_demo(void)
{
/* 屏幕 */
lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE); // 禁止屏幕滚动
lv_obj_set_style_text_font(lv_scr_act(), &lv_font_montserrat_30, 0); // 设置文本字体
lv_obj_set_style_text_align(lv_scr_act(), LV_TEXT_ALIGN_CENTER, 0); // 设置文本居中对齐
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex3(0xffe), 0); // 设置背景颜色
/* 温度标签 */
lv_obj_t* t_label = lv_label_create(lv_scr_act()); // 创建温度标签
lv_obj_set_size(t_label, 400, 30); // 设置标签大小
lv_obj_align(t_label, LV_ALIGN_CENTER, -100, -30); // 设置标签位置
lv_label_set_text(t_label, "Temperatur: 26"); // 设置标签内容
/* 湿度标签 方法同上 */
lv_obj_t* h_label = lv_label_create(lv_scr_act());
lv_obj_set_size(h_label, 400, 30);
lv_obj_align_to(h_label, t_label, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
lv_label_set_text(h_label, "Humidity: 52");
/* 温度弧 */
lv_obj_t* h_arc = lv_arc_create(lv_scr_act()); // 创建湿度圆弧
lv_obj_remove_style(h_arc, NULL, LV_PART_KNOB); // 移除圆弧手柄
lv_obj_add_flag(h_arc, LV_OBJ_FLAG_CLICKABLE); // 禁止点击事件
lv_obj_set_size(h_arc, 400, 400); // 设置圆弧大小
lv_arc_set_angles(h_arc, 180, 270); // 设置前景弧角度
lv_arc_set_bg_angles(h_arc, 180, 270); // 设置背景弧角度
lv_obj_set_pos(h_arc, 580 - 400 / 2, 250 - 400 / 2); // 设置圆弧位置
lv_obj_set_style_arc_width(h_arc, 50, LV_PART_INDICATOR); // 设置前景弧宽度
lv_obj_set_style_arc_width(h_arc, 50, LV_PART_MAIN); // 设置背景弧宽度
lv_obj_set_style_arc_color(h_arc, lv_color_hex3(0xf60), LV_PART_INDICATOR); // 设置前景弧颜色
lv_obj_set_style_arc_color(h_arc, lv_color_hex3(0xfed), LV_PART_MAIN); // 设置背景弧颜色
lv_obj_set_style_arc_rounded(h_arc, false, LV_PART_MAIN); // 取消背景弧圆角
lv_arc_set_range(h_arc, 0, 100); // 设置圆弧范围
lv_arc_set_value(h_arc, 52); // 设置圆弧当前值
/* 湿度弧 方法同上 */
lv_obj_t* t_arc = lv_arc_create(lv_scr_act());
lv_obj_remove_style(t_arc, NULL, LV_PART_KNOB);
lv_obj_add_flag(t_arc, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(t_arc, 500, 500);
lv_arc_set_angles(t_arc, 180, 270);
lv_arc_set_bg_angles(t_arc, 180, 270);
lv_obj_set_pos(t_arc, 580 - 500 / 2, 250 - 500 / 2);
lv_obj_set_style_arc_width(t_arc, 50, LV_PART_INDICATOR);
lv_obj_set_style_arc_width(t_arc, 50, LV_PART_MAIN);
lv_obj_set_style_arc_color(t_arc, lv_color_hex3(0x09f), LV_PART_INDICATOR);
lv_obj_set_style_arc_color(t_arc, lv_color_hex3(0xdef), LV_PART_MAIN);
lv_obj_set_style_arc_rounded(t_arc, false, LV_PART_MAIN);
// lv_arc_set_range(t_arc, -30, 50); /* !!! 如果范围为负数,执行动画时可能会造成显示异常,故改为正数范围 */
// lv_arc_set_value(t_arc, 26);
lv_arc_set_range(t_arc, 0, 80);
lv_arc_set_value(t_arc, 26 + 30);
int time = 0; // 时间标记
int temp, humi; // 温湿度值
while (!lv_win32_quit_signal)
{
if (time >= 200) // 延时时间
{
time = 0; // 时间标记复位
temp = rand() % 70 + 6 ; // 简单随机数获取温湿度值
humi = rand() % 80 + 11;
_set_var_value_anim(t_arc, temp); // 动画设置圆弧的值
_set_var_value_anim(h_arc, humi);
lv_label_set_text_fmt(t_label, "Temperatur: %d", temp - 30); // 改变标签文本
lv_label_set_text_fmt(h_label, "Humidity: %d", humi);
}
time++; // 时间标记自增
lv_task_handler(); // lvgl任务处理函数
Sleep(1); // 延时函数
}
return;
}
五、API
1. 类型定义
// 弧的模式
typedef uint8_t lv_arc_mode_t
2. 枚举
enum {
LV_ARC_MODE_NORMAL, // 指标弧从最小值绘制到当前值
LV_ARC_MODE_SYMMETRICAL, // 指标弧从最大值到当前值逆时针绘制
LV_ARC_MODE_REVERSE // 指标弧从中间点绘制到当前值
};
3. 方法
/**
* @brief 创建一个弧
* @param parent 指向对象的指针,它将是新圆弧的父对象
* @return 指向创建的圆弧的指针
*/
lv_obj_t *lv_arc_create(lv_obj_t *parent);
/**
* @brief 设置圆弧的起始角度。0度: 右侧; 90度: 底部...
* @param arc 指向要设置的圆弧的指针
* @param start 起始角度
*/
void lv_arc_set_start_angle(lv_obj_t *arc, uint16_t start);
/**
* @brief 设置圆弧的结束角度。0度: 右侧; 90度: 底部...
* @param arc 指向要设置的圆弧的指针
* @param end 结束角度
*/
void lv_arc_set_end_angle(lv_obj_t *arc, uint16_t end);
/**
* @brief 设置圆弧的开始角度和结束角度
* @param arc 指向要设置的圆弧的指针
* @param start 开始角度
* @param end 结束角度
*/
void lv_arc_set_angles(lv_obj_t *arc, uint16_t start, uint16_t end);
/**
* @brief 设置弧形背景的起始角度
* @param arc 指向要设置的圆弧的指针
* @param start 起始角度
*/
void lv_arc_set_bg_start_angle(lv_obj_t *arc, uint16_t start);
/**
* @brief 设置弧形背景的结束角度
* @param arc 指向要设置的圆弧的指针
* @param end 结束角度
*/
void lv_arc_set_bg_end_angle(lv_obj_t *arc, uint16_t end);
/**
* @brief 设置弧形背景的起始角度和结束角度
* @param arc 指向要设置的圆弧的指针
* @param start 起始角度
* @param end 结束角度
*/
void lv_arc_set_bg_angles(lv_obj_t *arc, uint16_t start, uint16_t end);
/**
* @brief 设置整个圆弧的旋转
* @param arc 指向要设置的圆弧的指针
* @param rotation 旋转角度
*/
void lv_arc_set_rotation(lv_obj_t *arc, uint16_t rotation);
/**
* @brief 设置圆弧的类型
* @param arc 指向要设置的圆弧的指针
* @param type 圆弧类型
*/
void lv_arc_set_mode(lv_obj_t *arc, lv_arc_mode_t type);
/**
* @brief 设置圆弧的值
* @param arc 指向要设置的圆弧的指针
* @param value 圆弧的值
*/
void lv_arc_set_value(lv_obj_t *arc, int16_t value);
/**
* @brief 设置圆弧的范围
* @param arc 指向要设置的圆弧的指针
* @param min 最小值
* @param max 最大值
*/
void lv_arc_set_range(lv_obj_t *arc, int16_t min, int16_t max);
/**
* @brief 设置一个变化率来限制电弧到达按压点的速度。
* @param arc 指向目标圆弧的指针
* @param rate 变化率
*/
void lv_arc_set_change_rate(lv_obj_t *arc, uint16_t rate);
/**
* @brief 获取圆弧的起始角度。
* @param arc 指向目标圆弧的指针
* @return 起始角度 [0, 360]
*/
uint16_t lv_arc_get_angle_start(lv_obj_t *obj);
/**
* @brief 获取圆弧的结束角度。
* @param arc 指向圆弧的指针
* @return 结束角度 [0, 360]
*/
uint16_t lv_arc_get_angle_end(lv_obj_t *obj);
/**
* @brief 获取弧形背景的起始角度
* @param arc 指向圆弧的指针
* @return 角度 [0, 360]
*/
uint16_t lv_arc_get_bg_angle_start(lv_obj_t *obj);
/**
* @brief 获取弧形背景的结束角度
* @param arc 指向圆弧的指针
* @return 角度 [0, 360]
*/
uint16_t lv_arc_get_bg_angle_end(lv_obj_t *obj)
/**
* @brief 获取圆弧的值
* @param arc 指向圆弧的指针
* @return 圆弧的值
*/
int16_t lv_arc_get_value(const lv_obj_t *obj);
/**
* @brief 获取圆弧的最小值
* @param arc 指向圆弧的指针
* @return 圆弧的最小值
*/
int16_t lv_arc_get_min_value(const lv_obj_t *obj);
/**
* @brief 获取圆弧的最大值
* @param arc 指向圆弧的指针
* @return 圆弧的最大值
*/
int16_t lv_arc_get_max_value(const lv_obj_t *obj);
/**
* @brief 获取圆弧的模式
* @param arc 指向圆弧的指针
* @return 圆弧的模式
*/
lv_arc_mode_t lv_arc_get_mode(const lv_obj_t *obj);