Linux基础项目开发1:量产工具——文字系统(四)

前言:

前面我们已经把显示系统,输入系统的框架搭建好了,那么有了输入和显示,显示的内容应该是什么呢?这节就要让我们一起对显示的内容,文字系统进行搭建。

目录

一、数据结构抽象

1.描述一个文字的位图:

2.描述一个字库操作:

3.font_manager.h

二、实现Freetype代码

freetype.c

 三、文字管理

font_manager.c

四、单元测试 

1.font_test.c 

2.disp_manager.c

3.disp_manager.h 

4. common.h

5.unittest下的Makefile

6.font下的Makefile

7.顶层的Makefile 

五、上板测试


 

一、数据结构抽象

 描述字符的方式:1.位置、大小   2.点阵

        点阵可以从固定大小的点阵字体文件中获得,也可以从Freetype的矢量字体文件中获得,所以我们需要抽象出一个结构体用来描述这些字符,一个结构体描述一个文字的位图,一个结构体描述一个字库操作。

1.描述一个文字的位图:

2.描述一个字库操作:

        使用点阵绘制文字时:每个文字的大小一样,前后文件互不影响 ,使用Freetype绘制文字时:大小可能不同,前面文字会影响后面文字

 

对于单个Freetype字符,格式如下 

         我们要抽象出一个结构体FontBitMap,能描述一个“字符”:位置、大小、位图,我们还要抽象出一个结构体FontOpr,能描述字体的操作,比如Freetype的操作、固定点阵字体的操作

3.font_manager.h

#ifndef _FONT_MANAGER_H
#define _FONT_MANAGER_H#include <common.h>typedef struct FontBitMap {int iLeftUpX;int iLeftUpY;int iWidth;int iRows;int iCurOriginX;int iCurOriginY;int iNextOriginX;int iNextOriginY;unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;typedef struct FontOpr {char *name;int (*FontInit)(char *aFineName);int (*SetFontSize)(int iFontSize);int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);struct FontOpr *ptNext;
}FontOpr, *PFontOpr;void RegisterFont(PFontOpr ptFontOpr);void FontsRegister(void);int SelectAndInitFont(char *aFontOprName, char *aFontFileName);
int SetFontSize(int iFontSize);
int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap);#endif

第28行:链表

第30行:注册单个字符库 ,从链表里挑出想要的字库

第32行:在g_ptFonts链表里面挑出来你想要的字体文件

第33行:将找到的字体设置字体大小

第34行:将找到的字体设置位图

为了方便后续使用区域,我们进行如下操作,将区域定义到一个结构体上Region tRegion;

typedef struct FontBitMap {Region tRegion;int iCurOriginX;int iCurOriginY;int iNextOriginX;int iNextOriginY;unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;

这个 tRegiondisp manager.h中有声明

typedef struct Region {int iLeftUpX;int iLeftUpY;int iWidth;int iHeigh;
}Region, *PRegion;

二、实现Freetype代码

freetype.c

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <sys/ioctl.h>
#include <font_manager.h>#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_Hstatic FT_Face g_tFace;
static int g_iDefaultFontSize = 12;static int FreeTypeFontInit(char *aFineName)
{FT_Library    library;int error;error = FT_Init_FreeType( &library );                 /* initialize library */    if (error){printf("FT_Init_FreeType err\n");return -1;}error = FT_New_Face(library, aFineName, 0, &g_tFace ); /* create face object */if (error){printf("FT_New_Face err\n");return -1;}FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);return 0;
}static int FreeTypeSetFontSize(int iFontSize)
{FT_Set_Pixel_Sizes(g_tFace, iFontSize, 0);return 0;
}static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{int error;FT_Vector pen;FT_Glyph  glyph;pen.x = ptFontBitMap->iCurOriginX * 64; /* 单位: 1/64像素 */pen.y = ptFontBitMap->iCurOriginY * 64; /* 单位: 1/64像素 *//* 转换:transformation */FT_Set_Transform(g_tFace, 0, &pen);/* 加载位图: load glyph image into the slot (erase previous one) */error = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}ptFontBitMap->pucBuffer = slot->bitmap.buffer;ptFontBitMap->tRegion.iLeftUpX = slot->bitmap_left;ptFontBitMap->tRegion.iLeftUpY = ptFontBitMap->iCurOriginY*2 - slot->bitmap_top;ptFontBitMap->tRegion.iWidth   = slot->bitmap.width;ptFontBitMap->tRegion.iHeigh   = slot->bitmap.rows;ptFontBitMap->iNextOriginX = ptFontBitMap->iCurOriginX + slot->advance.x / 64;ptFontBitMap->iNextOriginY = ptFontBitMap->iCurOriginY;return 0;
}static FontOpr g_tFreetypeOpr = {.name          = "freetype",.FontInit      = FreeTypeFontInit,.SetFontSize   = FreeTypeSetFontSize,.GetFontBitMap = FreeTypeGetFontBitMap,
};void FreetypeRegister(void)
{RegisterFont(&g_tFreetypeOpr);
}
static FontOpr g_tFreetypeOpr

第86~91行:实现FontOpr这个结构体里面的函数

        第87行:之后可以通过freetype这个名字找到FontOpr这个结构体

        第88行:初始化函数

        第89行:自定义设置字符大小

        第90行:得到位图并且设置坐标值

第19行:对应字体文件 

第20行:对应字体大小

static int FreeTypeFontInit(char *aFineName)

第22~44行:进行初始化 

        第27行:初始化freetype库

        第34行:加载字体文件

        第41行:设置默认的字体大小

static int FreeTypeSetFontSize(int iFontSize)

第 46~50行:自定义设置字符大小

给一个字符的编码值如何得到它的位图呢? 

static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)

第52~83行:得到位图并且设置坐标值

        第55行:pen用来反推原点

        第57行:记录点阵

        第59、60行:根据位图原点的X和Y坐标反推原点

        第63行:转换

        第66行:加载位图

        第73行:存放点阵

        第75~80行:描述一个文字的位图

void FreetypeRegister(void)

第93~96行: 进行注册,上层font_manager.c提供

 三、文字管理

        我们可能要用到的字体有多种,那么怎么选择用哪个字符呢,所以我们要编写一个程序管理多种字符。

font_manager.c


#include <font_manager.h>
#include <string.h>static PFontOpr g_ptFonts = NULL;
static PFontOpr g_ptDefaulFontOpr = NULL;void RegisterFont(PFontOpr ptFontOpr)
{ptFontOpr->ptNext = g_ptFonts;g_ptFonts = ptFontOpr;
}void FontsRegister(void)
{extern void FreetypeRegister(void);FreetypeRegister();
}int SelectAndInitFont(char *aFontOprName, char *aFontFileName)
{PFontOpr ptTmp = g_ptFonts;while (ptTmp){if (strcmp(ptTmp->name, aFontOprName) == 0)break;ptTmp = ptTmp->ptNext;}if (!ptTmp)return -1;g_ptDefaulFontOpr = ptTmp;return ptTmp->FontInit(aFontFileName);
}int SetFontSize(int iFontSize)
{return g_ptDefaulFontOpr->SetFontSize(iFontSize);
}int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{return g_ptDefaulFontOpr->GetFontBitMap(dwCode, ptFontBitMap);
}

实现这四个函数

第6行: 注册的单个字库链表头放到g_ptFonts

第7行:将22~37行找到的字库名字保存在g_ptDefaulFontOpr

void RegisterFont(PFontOpr ptFontOpr)

第10~14行:实现与freetype.c链接的链表

void FontsRegister(void)

第16~20行:实现多个字体的注册

        第18行:调用底层代码提供一个注册函数,注册单个字库,从链表里挑出想要的字库

假设你有多个字库,你要选择某一个,要提供一个SelectAndInitFont字体文件

int SelectAndInitFont(char *aFontOprName, char *aFontFileName)

 第22~37行:首先在g_ptFonts链表里面挑出来你想要的字体文件

        aFontOprName表示字库操作的名字,aFontFileName表示字体文件的名字

        第24行:在链表里面挑出来

        第27行:表示已经找到了

        第29行:没有找到,继续在链表里的下一个位置找

        第32行:表示不存在

        第35行:如果存在则调用初始化函数

int SetFontSize(int iFontSize)

第39~42行:将找到的字体设置字体大小

int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)

 第44~47行:将找到的字体设置位图

四、单元测试 

1.font_test.c 

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <font_manager.h>
#include <disp_manager.h>#define FONTDATAMAX 4096static const unsigned char fontdata_8x16[FONTDATAMAX] = {//此处点阵省略.........};/*********************************************************************** 函数名称: lcd_put_ascii* 功能描述: 在LCD指定位置上显示一个8*16的字符* 输入参数: x坐标,y坐标,ascii码* 输出参数: 无* 返 回 值: 无***********************************************************************/ 
void lcd_put_ascii(int x, int y, unsigned char c)
{unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];int i, b;unsigned char byte;for (i = 0; i < 16; i++){byte = dots[i];for (b = 7; b >= 0; b--){if (byte & (1<<b)){/* show */PutPixel(x+7-b, y+i, 0xffffff); /* 白 */}else{/* hide */PutPixel(x+7-b, y+i, 0); /* 黑 */}}}
}int main(int argc, char **argv)
{PDispBuff ptBuffer;int error;FontBitMap tFontBitMap;char *str= "Hello Linux";int i = 0;int lcd_x;int lcd_y;int font_size;if (argc != 5){printf("Usage: %s <font_file> <lcd_x> <lcd_y> <font_size>\n", argv[0]);return -1;}lcd_x = strtol(argv[2], NULL, 0);lcd_y = strtol(argv[3], NULL, 0);font_size  = strtol(argv[4], NULL, 0);DisplayInit();SelectDefaultDisplay("fb");InitDefaultDisplay();ptBuffer = GetDisplayBuffer();FontsRegister();error = SelectAndInitFont("freetype", argv[1]);if (error){printf("SelectAndInitFont err\n");return -1;}SetFontSize(font_size);while (str[i]){/* get bitmap */tFontBitMap.iCurOriginX = lcd_x;tFontBitMap.iCurOriginY = lcd_y;error = GetFontBitMap(str[i], &tFontBitMap);if (error){printf("SelectAndInitFont err\n");return -1;}/* draw on buffer */		DrawFontBitMap(&tFontBitMap,0xff0000);//0xff0000为红色/* flush to lcd/web */		FlushDisplayRegion(&tFontBitMap.tRegion, ptBuffer);lcd_x = tFontBitMap.iNextOriginX;lcd_y = tFontBitMap.iNextOriginY;	i++;}return 0;	
}

第60行:保存字符位图

第61行:想要显示的字符串

第68~72行:打印出具体用法    

                     <font_file>                字体文件

                     <lcd_x> <lcd_y>      显示的位置  

                     <font_size>              字体的大小

第74、75行:将字符串转化成整数传入到lcd_xlcd_y

第77行:将字符串转化成整数传入到 font_size

第86行:获得显示的设备

第88行:FontsRegister()注册单个字符库 ,从链表里挑出想要的字库

第90行:SelectAndInitFont("freetype", argv[1])去选择freetype字库操作,传入argv[1]字体文件

第97行:SetFontSize设置字体大小

第102、103行:绘制图像的原点 

第104行:GetFontBitMap得到字符位图

第112行:把位图绘制出来,绘制到默认设备中

第115行:绘制的内容刷到LCD或者web上

第118、119行:绘制完后取下一个位图的坐标

2.disp_manager.c

disp_manager.c中实现位图绘制

void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)

void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)
{int i, j, p, q;int x = ptFontBitMap->tRegion.iLeftUpX;int y = ptFontBitMap->tRegion.iLeftUpY;int x_max = x + ptFontBitMap->tRegion.iWidth;int y_max = y + ptFontBitMap->tRegion.iHeigh;int width = ptFontBitMap->tRegion.iWidth;unsigned char *buffer = ptFontBitMap->pucBuffer;//printf("x = %d, y = %d\n", x, y);for ( j = y, q = 0; j < y_max; j++, q++ ){for ( i = x, p = 0; i < x_max; i++, p++ ){if ( i < 0      || j < 0       ||i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres )continue;//image[j][i] |= bitmap->buffer[q * bitmap->width + p];if (buffer[q * width + p])PutPixel(i, j, dwColor);}}}

3.disp_manager.h 

声明函数DrawFontBitMap

void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);

头文件包含#include <font_manager.h>

#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H#include <common.h>
#include <font_manager.h>typedef struct DispBuff {int iXres;int iYres;int iBpp;char *buff;
}DispBuff, *PDispBuff;typedef struct DispOpr {char *name;int (*DeviceInit)(void);int (*DeviceExit)(void);int (*GetBuffer)(PDispBuff ptDispBuff);int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);struct DispOpr *ptNext;
}DispOpr, *PDispOpr;void RegisterDisplay(PDispOpr ptDispOpr);void DisplayInit(void);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
int PutPixel(int x, int y, unsigned int dwColor);
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff);
PDispBuff GetDisplayBuffer(void);
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);#endif

4. common.h

        因为显示系统和文字系统都需要用到这个区域结构体,所以我们直接把它拿出来定义成一个公共的头文件

#ifndef _COMMON_H
#define _COMMON_H#ifndef NULL
#define NULL (void *)0
#endiftypedef struct Region {int iLeftUpX;int iLeftUpY;int iWidth;int iHeigh;
}Region, *PRegion;#endif

5.unittest下的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := #obj-y += disp_test.o
#obj-y += input_test.o
obj-y += font_test.o

6.font下的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := obj-y += font_manager.o
obj-y += freetype.o

7.顶层的Makefile 


CROSS_COMPILE ?= 
AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nmSTRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMPCFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/includeLDFLAGS := -lts -lpthread -lfreetypeexport CFLAGS LDFLAGSTOPDIR := $(shell pwd)
export TOPDIRTARGET := testobj-y += display/
obj-y += input/
obj-y += font/
obj-y += unittest/all : start_recursive_build $(TARGET)@echo $(TARGET) has been built!start_recursive_build:make -C ./ -f $(TOPDIR)/Makefile.build$(TARGET) : built-in.o$(CC) -o $(TARGET) built-in.o $(LDFLAGS)clean:rm -f $(shell find -name "*.o")rm -f $(TARGET)distclean:rm -f $(shell find -name "*.o")rm -f $(shell find -name "*.d")rm -f $(TARGET)

 第20行:链接库

LDFLAGS := -lts -lpthread -lfreetype

 第30~33行:打开这四个文件夹进行make

obj-y += display/
obj-y += input/
obj-y += font/
obj-y += unittest/

五、上板测试

book@100ask:17_font_unittest_ok$ make
book@100ask:17_font_unittest_ok$ cp -r 17_font_unittest_ok/ ~/nfs_rootfs/
[root@100ask:~]#  mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
[root@100ask:~]# cd /mnt/
[root@100ask:/mnt/17_font_unittest_ok]# ./test ./simsun.ttc 100 400 100

注意:编译时候要将字库文件一起上传上去

运行效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/189212.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu系统下搭建本地物联网mqtt服务器的步骤

那么假如我们需要做一些终端设备&#xff0c;例如温湿度传感器、光照等物联网采集设备要接入呢&#xff1f;怎么样才能将数据报送到服务器呢&#xff1f; 以下内容基于我们ubuntu系统下的emqx成功启动的基础上。我们可以用浏览器键入控制板的地址&#xff0c;如果启动成功&…

特征相关性计较

Pearson相关系数 用于度量两个连续型变量之间的线性关系。取值范围在-1到1之间&#xff0c;0表示无线性关系&#xff0c;1表示完全正相关&#xff0c;-1表示完全负相关 import pandas as pd# 创建一个包含两个连续型变量的DataFrame data {Variable1: [1, 2, 3, 4, 5],Vari…

iOS简单理解区分MVC、MVP、MVVM

MVC、MVP、MVVM 前言 这篇文章简单介绍MVC、MVP和MVVM三种架构&#xff0c;并配上一个简单的Swift demo来区分MVC和MVVM两种架构。 MVC 传统MVC 下图是传统结构MVC&#xff0c;可以看到这种结构是紧耦合的&#xff0c;不推荐使用。 苹果的MVC 如下图&#xff0c;这是苹果…

AI产业前瞻报告:探讨GPTs背后的产业逻辑:拉开AIGC应用生态的帷幕

今天分享的是AI系列深度研究报告&#xff1a;《AI产业前瞻报告&#xff1a;探讨GPTs背后的产业逻辑&#xff1a;拉开AIGC应用生态的帷幕》。 &#xff08;报告出品方&#xff1a;光大证券&#xff09; 报告共计&#xff1a;13页 1、GPTs 拉开 AIGC 应用生态的帷幕 1.1、 Ope…

系列二十二、各种注解

一、Import # 用法 1&#xff09;Import(User.class)&#xff1a;如果导入的是配置类&#xff0c;将会按照配置类正常解析&#xff0c;如果是个普通类就会解析成bean 2&#xff09;Import&#xff08;实现了ImportSelector接口的类.class&#xff09;&#xff1a;可以一次性注册…

Python爬虫基础之Scrapy框架详解

目录 1. 简介2. Scrapy的安装3. Scrapy的架构4. Scrapy的数据流程5. Scrapy开发流程5.1 创建项目5.2 创建Spider5.3 创建Item5.4 编写Spider5.5 运行Spider 参考文献 原文地址&#xff1a;https://program-park.top/2023/12/01/reptile_5/ 本文章中所有内容仅供学习交流使用&am…

0Ω电阻最大过流能力及作用用途

0Ω电阻最大过流能力及作用用途 0Ω电阻过流能力0Ω电阻的作用 0Ω电阻过流能力 0Ω电阻不一定是真正的0Ω电阻&#xff0c;0Ω电阻存在一定的阻值偏差&#xff0c;主要看生产电阻厂商做哪种了。厂商都是根据电阻标准文件 EN60115-2&#xff0c; 里头0Ω电阻实际最大阻值有 10…

JAVA全栈开发 day15_集合(Set接口、增强For循环、Map体系)

一、增加for遍历集合 语法&#xff1a; for(数据类型 变量名: 数组名或集合){​ }//集合遍历 &#xff0c;推荐使用增加for 1.静态导入 注意事项&#xff1a; 方法必须是静态注意不要和本类的方法同名&#xff0c;如果同名&#xff0c;记得加前缀&#xff0c;由此可…

Git——分支应用进阶

主要内容包括以下几个方面&#xff1a; 长期分支和短期分支的类型以及用途。多种分支模型&#xff0c;其中包括基于工作流的主题分支。不同分支模型的发布流程。在多个预览版程序中使用分支修复安全问题。远程跟踪分支和refspecs规范&#xff0c;以及默认远程版本库配置。拉取…

Mongodb 开启oplog,java监听oplog并写入关系型数据库

开启Oplog windows mongodb bin目录下找到配置文件/bin/mongod.cfg,配置如下&#xff1a; replication:replSetName: localoplogSizeMB: 1024双击mongo.exe 执行 rs.initiate({_id: "local", members: [{_id: 0, host: "localhost:27017"}]})若出现如…

深入理解前端路由:构建现代 Web 应用的基石(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

多线程(初阶六:单例模式)

一、单例模式的简单介绍 二、饿汉模式 三、懒汉模式 四、饿汉模式和懒汉模式的线程安全问题分析 一、单例模式的简单介绍 单例模式是一种设计模式&#xff0c;其中设计模式是软性的规定&#xff0c;与它关联的框架是硬性的规定&#xff0c;这些都是大佬已经设计好了的&…

QT线程的使用 循环中程序的等待

QT线程的使用 循环中程序的等待 先看效果1 pro文件2 头文件3 源文件4 ui文件先看效果 1 pro文件 QT += concurrent2 头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H

简述MyBatis、MyBatis-Plus、以及MyBatis-Plus的简单运用

什么是MyBatis MyBatis是一个开源的Java持久层框架&#xff0c;用于简化与关系型数据库的交互。它通过将SQL语句与Java代码进行分离&#xff0c;提供了一种优雅的方式来处理数据库操作。 MyBatis的核心思想是将SQL语句与Java方法进行映射&#xff0c;使得开发人员可以通过配置…

集成开发环境PyCharm的使用【侯小啾python领航计划系列(三)】

集成开发环境 PyCharm 的使用【侯小啾python领航计划系列(三)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

【Vue3+Ts项目】硅谷甄选 — 搭建后台管理系统模板

一、 项目初始化 一个项目要有统一的规范&#xff0c;需要使用eslintstylelintprettier来对我们的代码质量做检测和修复&#xff0c;需要使用husky来做commit拦截&#xff0c;需要使用commitlint来统一提交规范&#xff08;即统一提交信息&#xff09;&#xff0c;需要使用pre…

Python | 轻量ORM框架Peewee的基础使用(增删改查、自动创建模型类、事务装饰器)

文章目录 01 简介02 安装03 自动创建模型类04 基础使用4.1 查询4.2 新增4.3 更新4.4 删除 05 事务 01 简介 在使用python开发的过程中&#xff0c;有时需要一些简单的数据库操作&#xff0c;而Peewee正是理想的选择&#xff0c;它是一个小巧而灵活的 Python ORM&#xff08;对…

hadoop-3.3.5安装过程

准备资源三台虚拟机&#xff1a; 1&#xff09;准备3台服务器&#xff08;关闭防火墙、静态IP、主机名称&#xff09; 2&#xff09;安装JDK 3&#xff09;配置环境变量 4&#xff09;安装Hadoop 5&#xff09;配置环境变量 安装虚拟机&#xff08;略&#xff09;--1台即…

如何删除mac苹果电脑上面的流氓软件?

在使用苹果电脑的过程中&#xff0c;有时候我们也会遇到一些不需要的软件。无论是因为不再需要&#xff0c;或者是为了释放磁盘空间&#xff0c;删除这些软件是很重要的。本文将为大家介绍怎样删除苹果电脑上的软件&#xff01; CleanMyMac X全新版下载如下: https://wm.make…

elementUI实现根据屏幕大小自适应换行,栅格化布局

需求&#xff1a; 默认一行展示4个卡片&#xff1b;当屏幕小于某个大小的时候&#xff0c;一行展示3个卡片&#xff1b;再小就展示2个&#xff1b;以此类推&#xff0c;最小就展示1个。 效果卡片样式如下图&#xff1a; 默认一行4个 屏幕缩小到某个阈值&#xff0c;一行展示…