LVGL编写自定义控件:时间选择控件

Qt版本在此:Qt编写自定义控件:时间选择控件_qt如何写一个按钮时间-CSDN博客

代码:

bool pressed;
int hour{0};
int minute{0};
bool isEditHour{false};
lv_area_t txt_coords;

static void event_cb000(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);

    if(code == LV_EVENT_REFR_EXT_DRAW_SIZE)
    {
        lv_coord_t * s = (lv_coord_t *)lv_event_get_param(e);
        *s = LV_MAX(*s, 20);
    }
    else if(code == LV_EVENT_DRAW_POST_END)
    {
        lv_draw_rect_dsc_t rect_dsc;
        lv_draw_rect_dsc_init(&rect_dsc);
        lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &rect_dsc);
        rect_dsc.bg_color = lv_color_hex(0xe0e0e0);
        rect_dsc.bg_grad_color = lv_color_hex(0x1c1c1c);
        rect_dsc.bg_grad_dir = LV_GRAD_DIR_HOR;

        const lv_area_t * clip_area = (const lv_area_t *)lv_event_get_param(e);

        lv_area_t area = obj->coords;

        lv_draw_arc_dsc_t arc_dsc;
        lv_draw_arc_dsc_init(&arc_dsc); // 使用默认设置初始化
        lv_obj_init_draw_arc_dsc(obj,LV_PART_MAIN,&arc_dsc);
        arc_dsc.color = lv_color_hex(0x00FF00); // 设置线条颜色为红色
        arc_dsc.width = 3;

        // 计算圆心位置(这里以Canvas中心为例)
        lv_coord_t x = (area.x2 - area.x1) / 2 + area.x1;
        lv_coord_t y = (area.y2 - area.y1) / 2 + area.y1;
        lv_coord_t r = (area.x2 - area.x1) / 2;

        lv_draw_arc(x,y,r,0,360,clip_area,&arc_dsc);

        int side = LV_MIN(area.x2 - area.x1, area.y2 - area.y1)  * 0.36;
        int drawAngle;
        if(isEditHour)
        {
            drawAngle = hour * 15;
        }
        else
        {
            drawAngle = minute * 6;
        }

        lv_point_t centerPos = lv_point_t{x,y};

        lv_draw_line_dsc_t line_dsc;
        lv_draw_line_dsc_init(&line_dsc); // 初始化绘图描述符
        lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc);
        line_dsc.color = lv_color_hex(0xFF0000); // 设置线条颜色
        line_dsc.width = 2; // 设置线条宽度

        int A = 90 - drawAngle;
        double angle_rad_A = A * M_PI / 180.0; // 将角度转换为弧度

        lv_point_t endPos;
        endPos.x = centerPos.x + cos(angle_rad_A) * side;
        endPos.y = centerPos.y - sin(angle_rad_A) * side;
        // lv_draw_line(&centerPos, &endPos, clip_area, &line_dsc);

        lv_draw_arc(endPos.x,endPos.y,side * 0.25,0,360,clip_area,&arc_dsc);

        std::string time24 = std::to_string(hour) + "  :  " + std::to_string(minute);
        lv_point_t txt_size;
        lv_txt_get_size(&txt_size, time24.c_str(),
                        lv_obj_get_style_text_font(obj, LV_PART_MAIN),
                        lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN),
                        0,
                        LV_COORD_MAX, LV_TEXT_FLAG_NONE);

        txt_coords.x1 = area.x1 + (area.x2 - area.x1 - txt_size.x) / 2;
        txt_coords.y1 = area.y1 + (area.y2 - area.y1 - txt_size.y) / 2;
        txt_coords.x2 = txt_coords.x1 + txt_size.x;
        txt_coords.y2 = txt_coords.y1 + txt_size.y;

        lv_draw_label_dsc_t label_dsc;
        lv_draw_label_dsc_init(&label_dsc);
        lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc);

        lv_draw_label(&txt_coords, clip_area, &label_dsc, time24.c_str(), NULL);
    }
    else if(code == LV_EVENT_PRESSED)
    {
        lv_point_t point;
        lv_indev_get_point(lv_event_get_indev(e), &point); // 获取当前输入设备的点坐标

        if(_lv_area_is_point_on(&txt_coords,&point,0))
        {
            isEditHour = !isEditHour;
            lv_obj_set_style_text_color(obj,lv_color_hex(isEditHour ? 0x128bf1 : 0xff2222),LV_PART_MAIN);
        }
        else
        {
            pressed = true;
        }

        lv_obj_invalidate(obj);
    }
    else if(code == LV_EVENT_RELEASED)
    {
        pressed = false;
        lv_obj_invalidate(obj);
    }
    else if(code == LV_EVENT_PRESSING)
    {
        if(pressed)
        {
            lv_point_t point;
            lv_indev_get_point(lv_event_get_indev(e), &point); // 获取当前输入设备的点坐标

            lv_area_t area = obj->coords;
            lv_coord_t x = (area.x2 - area.x1) / 2 + area.x1;
            lv_coord_t y = (area.y2 - area.y1) / 2 + area.y1;

            lv_point_t centerPos = lv_point_t{x,y};

            {
                double angle = atan2(point.y-centerPos.y,point.x-centerPos.x); //两点之间的角度(弧度)
                angle = -angle*(180 / 3.1415926); //0°~180° - -180°~0°
                angle -= 90;

                if(angle < 0.0)
                {
                    angle = 360.0 - abs(angle);
                }
                angle = (360 - angle);

                if(isEditHour)
                {
                    hour = angle / 15;
                }
                else
                {
                    minute = angle / 6;
                }
            }
            lv_obj_invalidate(obj);
        }
    }
}

int main(int argc, char **argv)
{
    lv_init();
    hal_init();

    lv_log_register_print_cb(esp32_log_cb);

    {
        lv_obj_t * obj = lv_obj_create(lv_scr_act());
        lv_obj_set_size(obj, 200, 200);
        lv_obj_center(obj);

        auto style = new lv_style_t;
        lv_style_init(style);
        lv_style_set_bg_color(style,lv_color_hex(0xffffff));
        lv_style_set_radius(style, LV_RADIUS_CIRCLE);
        lv_style_set_border_color(style,lv_color_hex(0x00dd66));
        lv_style_set_border_width(style,0);
        lv_style_set_text_color(style,lv_color_hex(0x128bf1));
        lv_obj_add_style(obj, style, LV_PART_MAIN);

        lv_obj_add_event_cb(obj, event_cb000,LV_EVENT_ALL,0);
    }

    while (1)
    {
        lv_timer_handler();
        usleep(5 * 1000);
    }

    return 0;
}

效果:

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值