基于LVGL的简易聊天室

创建过程:

在GUI里配置好了一个大概的界面。聊天界面需要一个滑动页、一个输入框、一个文本框、一个发送按键。其中文本框属于滑动页,并且给发送按键添加上事件。

保存界面后,打开工程代码。

第一件事,是打开键盘使用的宏定义

随后,进入generated/events_init.c。在这里,可以看到我刚添加的事件:输出There is button

我对这个按键的要求是,要在按下时,把输入框的字符串发送给服务器,并且在屏幕右侧新增一条文本框,其中内容由输入框中的内容填充。

大概是这样的:

其中My_Create_label()是我自己封装的函数,用来创建新的文本框。

函数的三个参数分别是:文本内容、第几条消息、接收/发送(我这里设定的接收消息陈列在界面左侧,发送的消息在右侧)。

消息的label组件设置是直接从generated/setup_src_screen.c中对label_1的设定复制的,也就是我一开始在界面设置中写了Halo的那个文本。这可以确保,我的消息条的大小、风格都是一样的。这里我的发送和接收消息条设置了两个颜色,所以在其中用了一个if条件判断,分别对flags==0和flags==1做出不同的设置。

lv_obj_t * My_Create_label(char *text,int msg_count,int flags)
{
    //首先,创建文本框,其父对象是滑动页
    lv_obj_t * my_screen_label_1 = lv_label_create(guider_ui.screen_tileview_1_tile);
    int x=0;//设置一个消息条的起始横坐标参数
    if(flags ==0){//如何创建的消息条需求为接收到的消息
        x=20;
        lv_obj_set_style_bg_color(my_screen_label_1,lv_color_hex(0x00c53c),LV_PART_MAIN|LV_STATE_DEFAULT);
    }else if (flags==1)
    {
        x=800-75-(strlen(text)*16);
        if(x<=100){
            x=100;//避免消息过长,超出界面
        }
        lv_obj_set_style_bg_color(my_screen_label_1, lv_color_hex(0xff7f50),LV_PART_MAIN|LV_STATE_DEFAULT);
    }
    lv_obj_set_pos(my_screen_label_1, x, 40+35*msg_count);//纵坐标按照消息的条数依次增加
    lv_obj_set_size(my_screen_label_1, strlen(text)*16, 30);//尺寸大小按照文本内容和字体大小设置
    lv_label_set_text(my_screen_label_1, text);
    lv_label_set_long_mode(my_screen_label_1, LV_LABEL_LONG_WRAP);
    //Write style for my_screen_label_1, Part: LV_PART_MAIN, State: LV_STATE_DEFAULT.
    lv_obj_set_style_border_width(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_radius(my_screen_label_1, 10, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(my_screen_label_1, lv_color_hex(0x000000), LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(my_screen_label_1, &lv_font_montserratMedium_24, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(my_screen_label_1, 200, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_letter_space(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_line_space(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_text_align(my_screen_label_1, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(my_screen_label_1, 226, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_bg_grad_dir(my_screen_label_1, LV_GRAD_DIR_NONE, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_pad_top(my_screen_label_1, 1, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_pad_right(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_pad_bottom(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_pad_left(my_screen_label_1, 8, LV_PART_MAIN|LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(my_screen_label_1, 0, LV_PART_MAIN|LV_STATE_DEFAULT);
    return my_screen_label_1;
}

紧接着,我在这个源文件中创建了新线程,用于客户通信

void custom_init(lv_ui *ui)
{
    pthread_t tid;
    pthread_create(&tid, NULL, (void *)Client_net_pthread,NULL);
}
//客户网络通信的线程
int ckd;
void * Client_net_pthread(void * arg){
pthread_mutex_init(&my_custom_mutex, NULL);//初始化一个互斥锁
//1.创建套接字
    ckd = socket(AF_INET, SOCK_STREAM, 0);
    //2.连接服务器
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("139.196.139.147");
    int ret = connect(ckd, (struct sockaddr *)&addr, sizeof(addr));
    if(ret<0){
        printf("connect error\n");
        exit(0);
    }
    printf("connected\n");
    //3.读取信息
    char readbuff[1024];
    while ((1))
    {
        memset(readbuff,0,sizeof(readbuff));
        //pthread_mutex_lock(&lv_mutex_lock);
        int retu = read(ckd,readbuff,sizeof(readbuff));
        //pthread_mutex_unlock(&lv_mutex_lock);
        if(retu==0){
            printf("server close\n");
            close(ckd);
            exit(0);
        }
        count++;
        printf("count==%d\n",count);
        //加互斥锁
        pthread_mutex_lock(&my_custom_mutex);
        lv_obj_t* mylabel_2 = My_Create_label(readbuff,count,0);
        lv_obj_move_foreground(mylabel_2);
        lv_obj_scroll_to_view(mylabel_2,LV_ANIM_ON);
        //解锁
        pthread_mutex_unlock(&my_custom_mutex);
    }   
}

这里,我写入的服务器和端口号是乱写的o,记得更改。

因为LVGL本身并不支持多线程控制组件,所以我们在创建新消息条的前后,分别对一开始初始化的互斥锁执行了加锁和解锁。

但目前,我按键按下创建发送消息条时还没有加互斥锁。所以,我直接在main.c里执行这个环节。

到此,聊天界面的基础功能已经结构清晰,但防止优化导致的错误,我在Makefile文件中,更改了优化等级为0。

最终的效果如下:

你想了解如何使用 LVGL 创建一个简易计算器吗?下面是一个使用 LVGL 创建简易计算器的示例代码: ```c #include <lvgl.h> lv_obj_t *textbox; lv_obj_t *label; lv_obj_t *btns[16]; void btn_click_event(lv_obj_t *btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { char txt[2]; lv_btn_get_text(btn, txt); if (txt[0] == '=') { char result[16]; lv_textarea_get_text(textbox, result, sizeof(result)); int num1, num2; char op; sscanf(result, "%d %c %d", &num1, &op, &num2); int res; switch (op) { case '+': res = num1 + num2; break; case '-': res = num1 - num2; break; case '*': res = num1 * num2; break; case '/': res = num1 / num2; break; default: res = 0; break; } sprintf(result, "%d", res); lv_label_set_text(label, result); } else { lv_textarea_add_char(textbox, txt[0]); } } } void create_calculator(lv_obj_t *parent) { lv_obj_t *container = lv_cont_create(parent, NULL); lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_COLOR_WHITE); textbox = lv_textarea_create(container, NULL); lv_textarea_set_one_line(textbox, true); lv_obj_align(textbox, container, LV_ALIGN_IN_TOP_MID, 0, 10); label = lv_label_create(container, NULL); lv_obj_align(label, textbox, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); const char *btn_labels[16] = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" }; for (int i = 0; i < 16; i++) { btns[i] = lv_btn_create(container, NULL); lv_obj_set_event_cb(btns[i], btn_click_event); lv_obj_t *label = lv_label_create(btns[i], NULL); lv_label_set_text(label, btn_labels[i]); } lv_obj_set_pos(btns[0], 0, 100); lv_obj_set_pos(btns[1], 80, 100); lv_obj_set_pos(btns[2], 160, 100); lv_obj_set_pos(btns[3], 240, 100); lv_obj_set_pos(btns[4], 0, 180); lv_obj_set_pos(btns[5], 80, 180); lv_obj_set_pos(btns[6], 160, 180); lv_obj_set_pos(btns[7], 240, 180); lv_obj_set_pos(btns[8], 0, 260); lv_obj_set_pos(btns[9], 80, 260); lv_obj_set_pos(btns[10], 160, 260); lv_obj_set_pos(btns[11], 240, 260); lv_obj_set_pos(btns[12], 0, 340); lv_obj_set_pos(btns[13], 80, 340); lv_obj_set_pos(btns[14], 160, 340); lv_obj_set_pos(btns[15], 240, 340); } int main(void) { lv_init(); lv_obj_t *scr = lv_scr_act(); create_calculator(scr); while (1) { lv_task_handler(); usleep(5000); } return 0; } ``` 这个示例代码使用了 LVGL 库来创建一个简易计算器。它使用了文本框、标签和按钮来实现计算器的功能。你可以根据需要进行修改和扩展。记得在编译和运行代码之前,确保已经正确配置好了 LVGL 库。 希望这可以帮助到你!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值