You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在LVGL中实现可正确递增的时间刻度X轴?

如何在LVGL中实现可正确递增的时间刻度X轴?

嗨,我来帮你解决这个问题!你遇到的情况应该是初始化X轴刻度时只固定了一个时间值,没有根据每个刻度的位置计算对应的递增时间。下面是具体的解决思路和代码示例,都是基于最新LVGL master分支的:

核心思路

LVGL的轴刻度标签支持自定义格式化回调函数,我们可以利用这个回调,根据每个刻度的数值偏移量来计算对应的时间,而不是用固定的初始时间。这样每个刻度就能显示递增的HH:MM:SS了。

具体实现步骤

  1. 定义起始时间基准
    先确定时间轴的起始点,可以用系统时间,也可以用LVGL内部的tick值(更适合嵌入式环境,不依赖系统时间)。这里两种方式都给你示例:

    • 用系统时间的方式:

      static time_t start_time; // 记录时间轴的起始时间
      
    • 用LVGL内部tick的方式(推荐嵌入式场景):

      static uint32_t start_tick; // 记录时间轴起始时的LVGL tick值(单位ms)
      
  2. 编写自定义刻度标签格式化函数
    这个函数会被LVGL调用,传入每个刻度的数值(比如0、1、2...对应秒数偏移),我们把这个偏移量转换成对应的HH:MM:SS格式:

    • 系统时间版本:

      static char * time_axis_label_formatter(lv_obj_t * axis, int32_t value) {
          static char buf[10]; // 静态缓冲区,用于返回格式化后的字符串
          // value是当前刻度对应的秒数偏移,计算该刻度的实际时间
          time_t tick_time = start_time + value;
          struct tm * tm_info = localtime(&tick_time);
          // 格式化为HH:MM:SS
          strftime(buf, sizeof(buf), "%H:%M:%S", tm_info);
          return buf;
      }
      
    • LVGL tick版本:

      static char * time_axis_label_formatter(lv_obj_t * axis, int32_t value) {
          static char buf[10];
          // value是秒数偏移,转换成LVGL tick的ms值
          uint32_t total_ms = start_tick + value * 1000;
          uint32_t total_sec = total_ms / 1000;
          // 拆分时、分、秒
          uint8_t h = total_sec / 3600;
          uint8_t m = (total_sec % 3600) / 60;
          uint8_t s = total_sec % 60;
          // 格式化输出
          snprintf(buf, sizeof(buf), "%02d:%02d:%02d", h, m, s);
          return buf;
      }
      
  3. 初始化时间轴并绑定格式化函数
    在创建X轴对象后,把上面的回调函数绑定到轴上,同时设置刻度范围和间隔:

    // 假设你的轴对象是axis_x(从图表中获取或直接创建)
    lv_obj_t * axis_x = lv_chart_get_axis(chart, LV_CHART_AXIS_PRIMARY_X);
    
    // 绑定自定义格式化函数
    lv_axis_set_label_formatter_cb(axis_x, time_axis_label_formatter);
    
    // 设置刻度范围:比如显示0到60秒(1分钟的时间轴)
    lv_axis_set_range(axis_x, 0, 60);
    
    // 设置刻度样式:每1秒一个小刻度,每5秒一个带标签的大刻度
    lv_axis_set_tick_length(axis_x, 5, 10); // 小刻度长度5px,大刻度10px
    lv_axis_set_major_tick_count(axis_x, 13); // 0、5、10...60,共13个大刻度
    lv_axis_set_minor_tick_count(axis_x, 4); // 每个大刻度间4个小刻度
    
  4. 如果需要实时推进时间轴(可选)
    如果你的时间轴是动态滚动的(比如实时显示流逝的时间),可以用LVGL定时器每秒更新起始时间并刷新轴:

    static void time_axis_update_timer(lv_timer_t * timer) {
        lv_obj_t * axis_x = timer->user_data;
        // 每秒推进1秒
        start_time += 1; // 系统时间版本
        // start_tick += 1000; // LVGL tick版本
        // 刷新轴,让标签重新计算
        lv_obj_invalidate(axis_x);
    }
    
    // 在初始化时创建定时器(间隔1000ms,即1秒)
    lv_timer_create(time_axis_update_timer, 1000, axis_x);
    

一些优化建议

  • 如果刻度比较密集,HH:MM:SS可能会挤在一起,可以调整标签显示逻辑:比如只给每5秒的大刻度显示完整时间,小刻度只显示秒数。
  • 静态缓冲区在单线程LVGL应用中没问题,如果是多线程场景,可以改用线程本地存储或者动态分配(记得及时释放内存避免泄漏)。
  • 若不需要时区转换,系统时间版本可以用gmtime代替localtime,得到UTC时间。

备注:内容来源于stack exchange,提问作者triz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:34:36