当前位置: 首页 > news >正文

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器(非直接运行图形库)

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器(非直接运行图形库)

打包开源地址:
Qt函数库gitee地址

更新以gitee为准

移植后的demo工程:
gitee
有些没实现的 后续我会继续优化

文章目录

  • 别碰瓷看清楚:是移植,不是直接运行LVGL
  • Qt的C/C++混编
  • Qt的模拟显示触摸屏
  • LVGL的API函数编写
  • LVGL文件移植
  • LVGL工程配置
  • LVGL显示配置
  • LVGL触摸配置
  • 主线程初始化和定时器轮询
  • 测试
  • 附录:C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)
    • C语言与C++的不同
    • C++中写C语言代码
    • C语言到C++的知识点
    • Qt开发中需要了解的C++基础知识
      • namespace
      • 输入输出
      • 字符串类型
      • class类
        • 构造函数和析构函数(解析函数)
        • 类的继承

别碰瓷看清楚:是移植,不是直接运行LVGL

LVGL是一种轻量级嵌入式图像界面库 且不需要多线程就能跑通
这里的在Qt上面移植LVGL并不是用Qt的IDE去建立一个没有Qt应用的工程 然后编译运行带SDL2等图形库的程序 从而实现在PC上运行LVGL
而是将Qt的窗口作为一个完整的嵌入式设备进行移植 使LVGL调用Qt窗口来进行显示和输入

说到FreeRTOS和LVGL这两种模拟多线程代表 我的个人理解就是:
FreeRTOS是硬件上的系统移植 其根据不同架构调用了硬件底层中断 systick等外设 以实现任务调度 属于用外设硬件模拟的多线程
LVGL的多线程是用两个定时器中断 不断刷新页面 进行操作 其触摸延迟至少得5ms 属于软件层面的多线程运行 实际上就相当于一个while 1里面不断刷新页面罢了
很早之前用51单片机+LCD1602写界面也是用一个while+状态判断来写的

Qt的C/C++混编

C++是兼容C的
在Qt的工程里面 可以直接添加C文件
但是调用C文件时 却不能直接拿来用
除了导入C文件对应的头文件函数声明外
还需要加上extern "C"来表示下面代码按C语言文件的方式编译
譬如

#ifdef __cplusplus
extern "C" {
#endif...//C文件的函数声明#ifdef __cplusplus
}
#endif

这样才能正常调用不报错

另外 在C文件中 当然就用不了C++的函数
不过又想实现交互 有两种解决方式:
分别导入<csignal><signal.h>
自己给自己的进程发送信号
或者 直接将要调用C++函数的C文件改成cpp文件

显然 后者更方便

但在混编时 只需要写一个总的接口函数文件用于调用即可 该接口文件可以调用C++的函数
另外也可以调用子类的C语言函数

譬如A.cpp操作B.c 直接调用即可
但是B.c如果想给A.cpp的槽函数信号 再去判断做什么事(调用emit函数) 则可以定义一个C.cpp 在C.cpp中发送emit来做判断 然后再去操作B.c

Qt的模拟显示触摸屏

通过QWidget可以模拟出一个显示屏
【Qt开发】QWidget的虚拟触摸显示屏配置 QPainter、QPixmap以及resizeEvent、paintEvent、mouseEvent鼠标输入事件
同时采样信号队列的形式
去捕获按键输入等等

        connect(this, SIGNAL(goto_setStyle(int)),this, SLOT(setStyle(int)),Qt::QueuedConnection);connect(this, SIGNAL(goto_setWidth(int)),this, SLOT(setWidth(int)),Qt::QueuedConnection);connect(this, SIGNAL(goto_setColor(QColor)),this, SLOT(setColor(QColor)),Qt::QueuedConnection);connect(this, SIGNAL(goto_setBack(QColor)),this, SLOT(setBack(QColor)),Qt::QueuedConnection);connect(this, SIGNAL(goto_clear()),this, SLOT(clear()),Qt::QueuedConnection);connect(this, SIGNAL(goto_drawPoint(QPoint)),this, SLOT(drawPoint(QPoint)),Qt::QueuedConnection);connect(this, SIGNAL(goto_drawPoints(QPoint*,int)),this, SLOT(drawPoints(QPoint*,int)),Qt::QueuedConnection);connect(this, SIGNAL(goto_drawLine(QPoint,QPoint)),this, SLOT(drawLine(QPoint,QPoint)),Qt::QueuedConnection);connect(this, SIGNAL(goto_setTextStyle(int)),this, SLOT(setTextStyle(int)),Qt::QueuedConnection);connect(this, SIGNAL(goto_setTextFont(QString,int)),this, SLOT(setTextFont(QString,int)),Qt::QueuedConnection);connect(this, SIGNAL(goto_drawText(QRectF,QString)),this, SLOT(drawText(QRectF,QString)),Qt::QueuedConnection);connect(this, SIGNAL(goto_fillRect(QPoint,QPoint)),this, SLOT(fillRect(QPoint,QPoint)),Qt::QueuedConnection);
signals:void goto_setStyle(int s);void goto_setWidth(int w);void goto_setColor(QColor c);void goto_clear(void);void goto_setBack(QColor c);void goto_setTextStyle(int text_style);void goto_setTextFont(QString strfont,int size);void goto_drawText(QRectF rectangle,QString text);void goto_drawPoint(QPoint p);void goto_drawPoints(QPoint *p,int pointCount);void goto_drawLine(QPoint p1,QPoint p2);void mouse_signal(int mode,QPoint p);void goto_fillRect(QPoint p1,QPoint p2);

模拟的触摸屏只需要触摸功能即可

LVGL的API函数编写

在触摸显示屏上移植LVGL 涉及到的API只有画点、面,触摸按下、松开,触摸坐标函数
以上面的模拟显示屏为接口 编写LVGL的API函数如下:

#include "LVGL_API.h"LVGL_API_Class *LVGL_API;void drawPoint(int x,int y,unsigned short color)
{emit LVGL_API->display->goto_setStyle(1);QPoint p(x,y);int r=0;int g=0;int b=0;r=(color>>11)*8;g=((color>>5)&0x003F)*4;b=(color&0x001F)*8;QColor c(r,g,b);emit LVGL_API->display->goto_setColor(c);emit LVGL_API->display->goto_drawPoint(p);emit LVGL_API->display->goto_setStyle(0);
}void drawLine(int x1,int y1,int x2,int y2,unsigned short color)
{emit LVGL_API->display->goto_setStyle(1);QPoint p1(x1,y1);QPoint p2(x2,y2);int r=0;int g=0;int b=0;r=(color>>11)*8;g=((color>>5)&0x003F)*4;b=(color&0x001F)*8;QColor c(r,g,b);emit LVGL_API->display->goto_setColor(c);emit LVGL_API->display->goto_drawLine(p1,p2);emit LVGL_API->display->goto_setStyle(0);
}void fillRect_drawLine(int x1,int y1,int x2,int y2)
{QPoint p1(x1,y1);QPoint p2(x2,y2);emit LVGL_API->display->goto_drawLine(p1,p2);
}void fillRect(int x1,int y1,int x2,int y2,unsigned short color)
{
#if 0emit LVGL_API->display->goto_setStyle(1);QPoint p1(x1,y1);QPoint p2(x2,y2);QPoint p3(x1,y2);QPoint p4(x2,y1);int r=0;int g=0;int b=0;r=(color>>11)*8;g=((color>>5)&0x003F)*4;b=(color&0x001F)*8;QColor c(r,g,b);emit LVGL_API->display->goto_setColor(c);emit LVGL_API->display->goto_drawLine(p1,p3);emit LVGL_API->display->goto_drawLine(p1,p4);emit LVGL_API->display->goto_drawLine(p2,p3);emit LVGL_API->display->goto_drawLine(p2,p4);emit LVGL_API->display->goto_fillRect(p1,p2);emit LVGL_API->display->goto_setStyle(0);
#elseint i=0;emit LVGL_API->display->goto_setStyle(1);int r=0;int g=0;int b=0;r=(color>>11)*8;g=((color>>5)&0x003F)*4;b=(color&0x001F)*8;QColor c(r,g,b);emit LVGL_API->display->goto_setColor(c);for(i=0;i<=y2-y1;i++){fillRect_drawLine(x1,y1+i,x2,y1+i);}emit LVGL_API->display->goto_setStyle(0);
#endif
}void Init_LVGL_API(MY_Display *dis)
{LVGL_API = new LVGL_API_Class(dis);
}
#ifndef LVGL_API_H
#define LVGL_API_H
#include "MY_QT_DEF.h"void drawPoint(int x,int y,unsigned short color);
void fillRect(int x1,int y1,int x2,int y2,unsigned short color);
void drawLine(int x1,int y1,int x2,int y2,unsigned short color);class LVGL_API_Class;
class LVGL_API_Class: public QObject
{Q_OBJECTpublic:int Touch_x;int Touch_y;int Touch;MY_Display *display;LVGL_API_Class(MY_Display *dis=nullptr){Touch=0;if(dis!=nullptr){display=dis;connect(display, SIGNAL(mouse_signal(int,QPoint)),this, SLOT(TouchEvent(int,QPoint)),Qt::QueuedConnection);emit display->goto_setStyle(0);}}~LVGL_API_Class(void){}
public slots:void TouchEvent(int mode,QPoint p){if(mode==2){Touch=0;}else{Touch=1;}Touch_x=p.x();Touch_y=p.y();}
};extern LVGL_API_Class *LVGL_API;void Init_LVGL_API(MY_Display *dis);#endif // LVGL_API_H

其中 画面提供了两种方式 一个是for循环画线遍历 一个是直接填充然后再画边框
但这两个在Qt上实现对LVGL的兼容性不太好(Qt会将比较小的像素点给优化掉)
所以在LVGL显示方面 还是选择画点函数吧
譬如画点是正常的:
在这里插入图片描述
画面就糊掉了
在这里插入图片描述

LVGL文件移植

移植与在嵌入式设备上移植相似
直接按照STM32的移植方式进行即可
这里用的LVGL库版本是8.3
下载后 实际需要移植的就下面三个文件夹和两个文件
在这里插入图片描述
将这些文件复制到一个单独的文件夹 比如LVGL
在这里插入图片描述
并且删除掉_template后缀
在examples中只保留porting 文件夹
同样删除_template后缀
在这里插入图片描述
然后这个LVGL文件夹里面的内容就是我们要移植的文件 适用于所有工程
包括STM32、Qt、C工程等等

LVGL工程配置

将上面的文件拷贝到Qt工程中
不要将LVGL文件夹整个拷贝 而是将里面的内容拷贝过来
用命令表示的区别就是 一个是cp ./ 一个是 cp ./* 这里是后者
这是因为Qt的搜素头文件路径默认就是根目录
而LVGL里面的文件导入则是以相对路径来的 譬如src下的文件:
在这里插入图片描述
这样一看就明白了吧
当然 你直接拷个文件夹过来也不是不行 那你就得弄好相对路径

在源文件和头文件中添加
在这里插入图片描述
直接点击Add Existing Directory 即可筛选

要添加的文件如下:

首先是两个主要头文件:
lv_conf.h
lvgl.h

porting目录 下的四个文件
lv_port_disp.c 、lv_port_disp.h、 lv_port_indev.c、lv_port_indev.h

src 下的所有C文件

除此之外 其他的一律不要添加
可以按如下进行添加:
在这里插入图片描述
另外 如果你用的不是Qt Creator 那么就需要添加头文件搜素路径

LVGL显示配置

打开 lv_conf.h 修改文件
表示启用
在这里插入图片描述
打开 lv_port_disp.h
同样启用 并且头文件路径改一下
在这里插入图片描述
打开 lv_port_disp.c
启用 并且删除后缀
在这里插入图片描述
在 lv_port_disp.c中添加我们的LVGL_API.h
注意 LVGL_API.cpp是一个C++文件 所以为了能使用 需要将 lv_port_disp.c改成 lv_port_disp.cpp
同理 触摸的文件也要改
在这里插入图片描述
然后定义屏幕可用的大小
在这里插入图片描述
LVGL提供了三种缓存方式 选择一种 其他的注释
在这里插入图片描述
第一种最简单 而且不需要添加什么东西
先配置 配好了以后有时间自己再研究就好了

然后关联画点函数即可
在这里插入图片描述
这里有一种更为优化 刷新率更高的方式 就是直接移植填充一块区域的函数
但是就如上面所说的 Qt这块给优化掉了 导致细小边界看不清 所以就只能用画点函数

LVGL触摸配置

LVGL可以设置触摸、按键、鼠标事件
这里我们只用触摸
虽然Qt的鼠标事件也可以捕获 但是我们把所有的鼠标事件都定义为触摸就行了

配置如显示类似
在这里插入图片描述
一样导入文件定义区域
在这里插入图片描述
在93行以后 只保留触摸 注释掉鼠标和按键 一直到170行(除非你要使用)
在这里插入图片描述
添加检测触摸函数接口和获取坐标接口
在这里插入图片描述
即可

如果想看看触摸能不能生效 那么就添加一个画点的函数在触摸获取xy坐标的后面即可

帧率和触摸率还有待优化:
有些没实现的 后续我都会继续优化
在这里插入图片描述

主线程初始化和定时器轮询

在main中导入库:

#include "lvgl.h"                // 它为整个LVGL提供了更完整的头文件引用
#include "examples/porting/lv_port_disp.h"        // LVGL的显示支持
#include "examples/porting/lv_port_indev.h"       // LVGL的触屏支持

在窗口的构造函数中初始化模拟触摸屏后 进行LVGL初始化

    lv_init();                             // LVGL 初始化lv_port_disp_init();                   // 注册LVGL的显示任务lv_port_indev_init();                  // 注册LVGL的触屏检测任务

建立两个定时器线程 一个1ms 一个5ms 分别调用lv_tick_inc(1);lv_timer_handler();

void timer0_callback(void * pCBParam,uint32_t Event,void * pArg)
{lv_tick_inc(1);
}void timer1_callback(void * pCBParam,uint32_t Event,void * pArg)
{lv_timer_handler();
}Timer0 = new MY_Timer(timer0_callback,1,true);Timer1 = new MY_Timer(timer1_callback,5,true);Timer0->Start_Timer();Timer1->Start_Timer();

这就是LVGL的心跳

测试

建立几个控件测试一下:


void button_evnet(lv_event_t * event)
{qDebug()<<event->code;lv_obj_t *btn = lv_event_get_target(event);                    // 获得调用这个回调函数的对象if (event->code == LV_EVENT_CLICKED){static uint8_t cnt = 0;cnt++;lv_obj_t *label = lv_obj_get_child(btn, NULL);             // 获取第1个子对象(我们在设计时,已安排了它的第1个子对象是一个label对象)lv_label_set_text_fmt(label, "Button: %d", cnt);           // 设置标签的文本,写法类似printf}
}//按钮lv_obj_t *myBtn = lv_btn_create(lv_scr_act());                               // 创建按钮; 父对象:当前活动屏幕lv_obj_set_pos(myBtn, 10, 10);                                               // 设置坐标lv_obj_set_size(myBtn, 120, 50);                                             // 设置大小lv_obj_add_event_cb(myBtn, button_evnet, LV_EVENT_CLICKED, NULL); //添加事件// 按钮上的文本lv_obj_t *label_btn = lv_label_create(myBtn);                                // 创建文本标签,父对象:上面的btn按钮lv_obj_align(label_btn, LV_ALIGN_CENTER, 0, 0);                              // 对齐于:父对象lv_label_set_text(label_btn, "Test");                                        // 设置标签的文本// 独立的标签lv_obj_t *myLabel = lv_label_create(lv_scr_act());                           // 创建文本标签; 父对象:当前活动屏幕lv_label_set_text(myLabel, "Hello world!");                                  // 设置标签的文本lv_obj_align(myLabel, LV_ALIGN_CENTER, 0, 0);                                // 对齐于:父对象lv_obj_align_to(myBtn, myLabel, LV_ALIGN_OUT_TOP_MID, 0, -20);               // 对齐于:某对象

运行后效果:
在这里插入图片描述
帧率信息显示在:
lv_conf.h中第282行,找到:LV_USE_PERF_MONITOR,原值:0, 修改为:1

内存显示则在:
lv_conf.h中第289行,找到:LV_USE_MEM_MONITOR,原值:0, 修改为:1

附录:C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)

C语言与C++的不同

C语言是一门主要是面向工程的语言
C++则是面向对象

C语言中 某些功能实现起来较为繁琐
比如结构体定义:

一般写作:

typedef struct stu_A
{
}A;

也可以写作:

typedef struct 
{
}A;

但 大括号后面的名称是不可省去的

不过 C++的写法就比较简单
除了支持上述写法外

也支持直接声明

typedef struct A
{
}

另外 C++是完全支持C语言库和语法的
不过C++里面的库也有些很方便的高级功能用法 只不过实现起来可能不如C的速度快

再者 C语言与C++的编译流程不一样
C语言没有函数重载 所以给编译器传参就是直接传函数名称
但是C++除了传函数名称外 还会穿函数的参数、类型等等 以实现函数重载

C++中写C语言代码

上文提到 C++可以完全兼容C的写法
但是编译流程也还是不一样
所以如果在编译层面进行C语言代码编译 则通常用以下方法:

extern "C"
{
...
}

表面大括号内的内容用C的方法进行编译

另外 如果还是用C++的编译器 但要实现C语言函数 则需要用到C语言的库

在C语言中 我们一般用如下方法导入库

#include <stdio.h>

此方法同样适用于C++ 但是C++可以更方便的写成去掉.h的方式
比如:

#include <iostream>

在C++中 为了调用C语言的库 可以采用在原库名称前加一个"c"的方式导入
如:

#include <cstdio>

这样就可以使用printf等函数了 甚至比C++的std方法更快

C语言到C++的知识点

在这里插入图片描述

Qt开发中需要了解的C++基础知识

namespace

C++面向对象的特性下诞生的一个名称
表示某个函数、变量在某个集合下 用作namespace
比如 <iostream>库中的关键字cin在std下 则写作std::cin
std就是namespace
::表示某空间下的某某
前面是空间名称 后面是变量、函数名称

using namespace可以告诉编译器以下都用xx名称空间
比如:

using namespace std;
cout<<"a";

如果没有告诉编译器所使用的空间名称 则要写成:

std::cout<<"a";

同样 可以自定义某一段代码属于哪个空间:

namespace xx
{
...
}

输入输出

在C++中 用iostream作为输入输出流的库

#include <iostream>

用cin和cout关键字进行输入和输出
如:

using namespace std;
int a=0;
cin>>a; //输入到acout<<a;  //输出a

类比scanf和printf
同样 还有一个关键字endl表示换行
cout和cin的传参是不固定的
由编译器自行裁定

字符串类型

在C语言中 常用char *表示字符串
但是在C++中 可以直接用string类型
比如:

char * s="456";
string str="123";

由于cout的特性 这两种字符串都可以直接打印
但如果使用C语言中printf的打印方式时 采用%s方式打印字符串 则不能传入string类型

class类

C++的核心就是class
同Python等支持面向对象的语言一样
可以理解成一个支持函数、继承、自动初始化、销毁的结构体
在class类中 有private私有、public公有变量
前者只能内部访问 后者可以外部调用使用
如:

class A
{
public:
int a;
private:
int b;
}

a可以用A.a的方式方位 b则外部无法访问

构造函数和析构函数(解析函数)

构造函数可以理解成对类的初始化 反之析构函数则是退出时进行销毁前的函数
两者需要与类的名称相同 析构函数则在前面加一个~表示非
如:

class A
{
public:
int a;
A();
~A();
private:
int b;
}A::A()
{
...
}A::~A()
{
...
}

构造函数可以定义传参 析构函数则不行

类的继承

如果有两个类A和B 想让A里面包含B 则可以写作继承的写法
继承后 A类的变量可以直接调用B下面的成员
如:

class B
{
int b;
}
class A: public B
{
int a;
}

在定义A后 可以访问到B的成员b 当然 继承也可以私有

相关文章:

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器(非直接运行图形库)

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器&#xff08;非直接运行图形库&#xff09; 打包开源地址&#xff1a; Qt函数库gitee地址 更新以gitee为准 移植后的demo工程&#xff1a; gitee 有些没实现的 后续我会继续优化 文章目录 别碰瓷看清楚&#xff1a;是移植&#…...

PostgreSQL UNION 操作符

PostgreSQL UNION 操作符 引言 PostgreSQL 是一种功能强大的开源对象关系型数据库管理系统,它以其稳定性、可靠性和先进的特性而闻名。在处理数据库查询时,我们经常需要合并来自不同表的数据,或者合并同一表的不同查询结果。这时,UNION 操作符就变得非常有用。本文将详细…...

spring boot 测试 mybatis mapper类

spring boot 测试 mybatis mapper类 针对 mybatis plus不启动 webserver指定加载 xml 【过滤 “classpath*:/mapper/**/*.xml” 下的xml】, mapper xml文件名和mapper java文件名称要一样&#xff0c;是根据文件名称过滤的。默认情况加载和解析所有mapper.xml 自定义 MapperT…...

Python发kafka消息

要在Python中向Kafka发送消息&#xff0c;你可以使用kafka-python库。首先&#xff0c;你需要安装这个库。如果你还没有安装它&#xff0c;可以通过pip来安装&#xff1a; bash pip install kafka-python 接下来是一个简单的例子&#xff0c;展示如何创建一个生产者&#xff0…...

zipkin 引申一:如何遍历jar目录下的exec.jar并选择对应序号的jar启动

文章目录 一、Zipin概述二、如何下载三、需求描述四、代码实现1. pom设置2. 相关工具类3. 核心代码 五、打包部署1. 打包&#xff0c;在项目目录执行mvn clean package2. 部署3. 运行以及停止 六、源码放送 一、Zipin概述 Zipkin是Twitter开源的分布式跟踪系统&#xff0c;基于…...

使用 httputils + protostuff 实现高性能 rpc

1、先讲讲 protobuf protobuf 一直是高性能序列化的代表之一&#xff08;google 出品&#xff09;。但是用起来&#xff0c;可难受了&#xff0c;你得先申明 “.proto” 配置文件&#xff0c;并且要把这个配置文件编译转成类。所以必然要学习新语法、新工具。 可能真的太难受…...

Facebook广告文案流量秘诀

Facebook 广告文案是制作有效 Facebook 广告的关键方面。它侧重于伴随广告视觉元素的文本内容。今天我们的博客将深入探讨成功的 Facebook 广告文案的秘密&#xff01; 一、广告文案怎么写&#xff1f; 正文&#xff1a;这是帖子的正文&#xff0c;出现在您姓名的正下方。它可…...

在Vue.js中生成二维码(将指定的url+参数 生成二维码)

在Vue.js中生成二维码&#xff0c;你可以使用JavaScript库如qrcode或qr.js。以下是一个简单的例子&#xff0c;展示如何在Vue组件中使用qrcode库将指定的URL加上参数生成二维码。 首先&#xff0c;你需要安装qrcode库。如果你使用的是npm或yarn&#xff0c;可以通过命令行安装…...

Face2QR:可根据人脸图像生成二维码,还可以扫描,以后个人名片就这样用了!

今天给大家介绍的是一种专为生成个性化二维码而设计的新方法Face2QR&#xff0c;可以将美观、人脸识别和可扫描性完美地融合在一起。 下图展示为Face2QR 生成的面部图像&#xff08;第一行&#xff09;和二维码图像&#xff08;第二行&#xff09;。生成的二维码不仅忠实地保留…...

【Linux网络编程】第六弹---构建TCP服务器:从基础到线程池版本的实现与测试详解

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】 目录 1、TcpServerMain.cc 2、TcpServer.hpp 2.1、TcpServer类基本结构 2.2、构造析构函数 2.3、InitServer(…...

XML 语言随笔

XML的含义 XML&#xff08;eXtensible Markup Language&#xff0c;可扩展标记语言&#xff09;是一种用于存储和传输数据的标记语言。XML与HTML&#xff08;HyperText Markup Language&#xff0c;超文本标记语言&#xff09;类似&#xff0c;但XML的设计目的是描述数据&…...

flex: 1 display:flex 导致的宽度失效问题

flex: 1 & display:flex 导致的宽度失效问题 问题复现 有这样的一个业务场景&#xff0c;详情项每行三项分别占33%宽度&#xff0c;每项有label字数不固定所以宽度不固定&#xff0c;还有content 占满标签剩余宽度&#xff0c;文字过多显示省略号&#xff0c; 鼠标划入展示…...

65页PDF | 企业IT信息化战略规划(限免下载)

一、前言 这份报告是企业IT信息化战略规划&#xff0c;报告详细阐述了企业在面对新兴技术成熟和行业竞争加剧的背景下&#xff0c;如何通过三个阶段的IT战略规划&#xff08;IT 1.0基础建设、IT 2.0运营效率、IT 3.0持续发展&#xff09;&#xff0c;系统地构建IT管理架构、应…...

15.三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&am…...

【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Notepad】---设置背景为护眼色&#xf…...

项目代码第2讲:从0实现LoginController.cs,UsersController.cs、User相关的后端接口对应的前端界面

一、User 1、使用数据注解设置主键和外键 设置主键&#xff1a;在User类的U_uid属性上使用[Key]注解。 设置外键&#xff1a;在Order类中&#xff0c;创建一个表示外键的属性&#xff08;例如UserU_uid&#xff09;&#xff0c;并使用[ForeignKey]注解指定它引用User类的哪个…...

电子商务人工智能指南 3/6 - 聊天机器人和客户服务

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…...

vue.js组件开发的所有流程

1. 设计组件架构 首先&#xff0c;你需要考虑应用的结构&#xff0c;决定哪些部分应该成为独立的组件。这包括&#xff1a; 提取重复的UI元素&#xff1a;如按钮、输入框、卡片等。 功能模块&#xff1a;例如登录框、导航栏、数据表格等。 2. 设置开发环境 安装Node.js&#xf…...

从零开始学TiDB(1) 核心组件架构概述

首先TiDB深度兼容MySQL 5.7 1. TiDB Server SQL语句的解析与编译&#xff1a;首先一条SQL语句最先到达的地方是TiDB Server集群&#xff0c;TiDB Server是无状态的&#xff0c;不存储数据&#xff0c;SQL 发过来之后TiDB Server 负责 解析&#xff0c;优化&#xff0c;编译 这…...

VsCode运行Ts文件

1. 生成package.json文件 npm init 2. 生成tsconfig.json文件 tsc --init 3. Vscode运行ts文件 在ts文件点击右键执行Run Code,执行ts文件...

初始化webpack应用示例

1、初始化npm mkdir webpack_test cd webpack_test npm init 2、安装webpack依赖 npm install webpack webpack-cli -D 3、添加文件夹&#xff0c;入口文件 mkdir src touch index.js touch add-content.js 文件夹结构 index.js import addContent from "./add-cont…...

liunx docker 部署 nacos seata sentinel

部署nacos 1.按要求创建好数据库 2.创建docker 容器 docker run -d --name nacos-server -p 8848:8848 -e MODEstandalone -e SPRING_DATASOURCE_PLATFORMmysql -e MYSQL_SERVICE_HOST172.17.251.166 -e MYSQL_SERVICE_DB_NAMEry-config -e MYSQL_SERVICE_PORT3306 -e MYSQL…...

MySQL面试

文章目录 事务隔离级别需要解决的问题事务隔离级别 MySQL 中是如何实现事务隔离的实现可重复读 什么是存储引擎如何定位慢查询分析慢查询原因MySQL超大分页怎么处理索引失效什么时候建立唯一索引、前缀索引、联合索引&#xff1f;redolog与binlog是如何保证一致的redolog刷盘时…...

linux运维之shell编程

Shell 编程在系统运维中及其重要 1. Shell 编程概述 Shell 是一种命令行解释器&#xff0c;能够执行操作系统的命令。Shell 脚本是一个包含一系列 Shell 命令的文件&#xff0c;它可以被执行&#xff0c;以自动化和批量处理任务。常用的 Shell 类型包括 bash、sh、zsh 等。Shel…...

ssm 多数据源 注解版本

application.xml 配置如下 <!-- 使用 DruidDataSource 数据源 --><bean id"primaryDataSource" class"com.alibaba.druid.pool.DruidDataSource" init-method"init" destroy-method"close"></bean> <!-- 使用 数…...

Nginx核心配置详解

一、配置文件说明 nginx官方帮助文档&#xff1a;nginx documentation nginx的配置文件的组成部分&#xff1a; 主配置文件&#xff1a;nginx.conf子配置文件: include conf.d/*.conffastcgi&#xff0c; uwsgi&#xff0c;scgi 等协议相关的配置文件mime.types&#xff1a;…...

十六(AJAX3)、XMLHttpRequest、Promise、简易axios封装、案例天气预报、lodash-debounce防抖

1. XMLHttpRequest 1.1 XMLHttpRequest-基本使用 /* 定义&#xff1a;XMLHttpRequest&#xff08;XHR&#xff09;对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL&#xff0c;获取数据。这允许网页在不影响用户操作的情况下&#xff0c;更…...

12.06 深度学习-预训练

# 使用更深的神经网络 经典神经网络 import torch import cv2 from torchvision.models import resnet18,ResNet18_Weights from torch import optim,nn from torch.utils.data import DataLoader from torchvision.datasets import CIFAR10 from torchvision import tr…...

【计算机网络】期末速成(2)

部分内容来源于网络&#xff0c;侵删~ 第五章 传输层 概述 传输层提供进程和进程之间的逻辑通信&#xff0c;靠**套接字Socket(主机IP地址&#xff0c;端口号)**找到应用进程。 传输层会对收到的报文进行差错检测。 比特流(物理层)-> 数据帧(数据链路层) -> 分组 / I…...

Python学习笔记10-作用域

作用域 定义&#xff1a;Python程序程序可以直接访问命名空间的正文区域 作用&#xff1a;决定了哪一部分区域可以访问哪个特定的名称 分类&#xff1a; 局部作用域&#xff08;Local&#xff09;闭包函数外的函数中&#xff08;Enclosing&#xff09;全局作用域&#xff0…...

Sui 主网升级至 V1.38.3

Sui 主网现已升级至 V1.38.3 版本&#xff0c;同时协议升级至 69 版本。请开发者及时关注并调整&#xff01; 其他升级要点如下所示&#xff1a; 协议 #20199 在共识快速路径投票中设置允许的轮次数量。 节点&#xff08;验证节点与全节点&#xff09; #20238 为验证节点…...

linux的vdagent框架设计

1、vdagent Linux 的 spice 客户代理由两部分组成&#xff0c;一个系统范围的守护进程 spice-vdagentd 和一个 X11 会话代理 spice-vdagent&#xff0c;每个 X11 会话有一个。spice-vdagentd 通过 Sys-V initscript 或 systemd 单元启动。 如下图&#xff1a;spice-vdagent&a…...

vue3+elementPlus封装的一体表格

目录结构 源码 exportOptions.js export default reactive([{label: 导出本页,key: 1,},{label: 导出全部,key: 2,}, ])index.vue <template><div class"flex flex-justify-between flex-items-end"><div><el-button-group><slot name…...

判断是否 AGP7+ 的方法

如何判断&#xff1f; /*** 是否是AGP7.0.0及以上* param project* return*/static boolean isAGP7_0_0(Project project) {def androidComponents project.extensions.findByName("androidComponents")if (androidComponents && androidComponents.hasProp…...

使用 Streamlit +gpt-4o实现有界面的图片内容分析

在上一篇利用gpt-4o分析图像的基础上&#xff0c;进一步将基于 Python 的 Streamlit 库&#xff0c;结合 OpenAI 的 API&#xff0c;构建一个简洁易用的有界面图片内容分析应用。通过该应用&#xff0c;用户可以轻松浏览本地图片&#xff0c;并获取图片的详细描述。 调用gpt-4o…...

树莓集团是如何链接政、产、企、校四个板块的?

树莓集团作为数字影像行业的积极探索者与推动者&#xff0c;我们通过多维度、深层次的战略举措&#xff0c;将政、产、企、校四个关键板块紧密链接在一起&#xff0c;实现了资源的高效整合与协同发展&#xff0c;共同为数字影像产业的繁荣贡献力量。 与政府的深度合作政府在产业…...

Fyne ( go跨平台GUI )中文文档-Fyne总览(二)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16及更高版本,ide为goland2021.2??????? ?这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne…...

MySQL数据库(3)-SQL基础语言学习

1. DDL数据定义语言 1.1 什么是DDL DDL&#xff08;Data Definition Language&#xff0c;数据定义语言&#xff09;是SQL语言的一部分&#xff0c;用于定义和修改数据库结构。DDL主要包括以下三类语句&#xff1a; 1.CREATE&#xff1a;用于创建数据库对象&#xff0c;如数…...

下拉框根据sql数据回显

vue <a-form-item label"XXXX" :labelCol"labelCol" :wrapperCol"wrapperCol" required><a-select v-decorator"[disputeType, validatorRules.disputeType]" style"width: 200px" placeholder"请选择XXXX&q…...

电池销售系统

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 摘 要 在当今信息爆炸的大时代&#xff0c;由于信息管理系统能够更有效便捷的完成信息的管理&#xff0c;越来越多的人及机构都已经引入和发展以信息管理系统为基础的信息化管理模式&#xff0c;随之信…...

四、镜像构建

四、镜像构建 从镜像大小上来说&#xff0c;一个比较小的镜像只有十几MB&#xff0c;而内核文件需要一百多MB&#xff0c;因此镜像里面是没有内核的&#xff0c;镜像是在被启动为容器后直接使用宿主机的内核&#xff0c;而镜像本身则只提供相应的rootfs&#xff0c;即系统正常…...

FastAPI 响应状态码:管理和自定义 HTTP Status Code

FastAPI 响应状态码&#xff1a;管理和自定义 HTTP Status Code 本文介绍了如何在 FastAPI 中声明、使用和修改 HTTP 状态码&#xff0c;涵盖了常见的 HTTP 状态码分类&#xff0c;如信息响应&#xff08;1xx&#xff09;、成功状态&#xff08;2xx&#xff09;、客户端错误&a…...

C#设计模式--原型模式(Prototype Pattern)

原型模式是一种创建型设计模式&#xff0c;它允许通过复制现有对象来创建新对象&#xff0c;而无需通过构造函数。这种方式可以提高性能&#xff0c;特别是在创建复杂对象时。C# 中可以通过实现 ICloneable 接口或自定义克隆方法来实现原型模式。 案例 1&#xff1a;文档编辑器…...

使用Goland对6.5840项目进行go build出现异常

使用Goland对6.5840项目进行go build出现异常 Lab地址: https://pdos.csail.mit.edu/6.824/labs/lab-mr.html项目地址: git://g.csail.mit.edu/6.5840-golabs-2024 6.5840运行环境: mac系统 goland git clone git://g.csail.mit.edu/6.5840-golabs-2024 6.5840 cd 6.5840/src…...

使用kibana实现es索引的数据映射和索引模版/组件模版

1 数据映射 数据映射官方链接 1.1 日期映射案例 1.创建一条索引。把索引中的字段生日映射为日期&#xff0c;并制定映射后的格式为年月日 PUT http://10.0.0.91:9200/zhiyong18-luckyboy-date {"mappings": {"properties": {"birthday": {&q…...

基于elementui的远程搜索下拉选择分页组件

在开发一个练手项目的时候&#xff0c;需要一个远程搜索的下拉选择组件&#xff1b; elementui自带的el-select支持远程搜索&#xff1b;但如果一次性查询的数据过多&#xff1b;会导致卡顿。故自己实现一个可分页的远程下拉选择组件 效果&#xff1a; 代码&#xff1a; <…...

每日一题 LCR 074. 合并区间

LCR 074. 合并区间 对遍历顺序注意一下就可以 class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {int n intervals.size();sort(intervals.begin(),intervals.end());int idx 0;vector<vector<int&g…...

Flink SQL

Overview | Apache Flink FlinkSQL开发步骤 Concepts & Common API | Apache Flink 添加依赖&#xff1a; <dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-api-java-bridge_2.11</artifactId><version>…...

[免费]SpringBoot+Vue企业OA自动化办公管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue企业OA自动化办公管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue企业OA自动化办公管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着信息技术在管理上越来越深入…...

Linux下编译安装METIS

本文记录Linux下编译安装METIS的流程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1 一、安装依赖 1.1 下载GKlib sudo apt-get install build-essential sudo apt-get install cmake 2.2 编译安装GKlib 下载GKlib代码&#xff0c; …...