easyx图形库

目录

1、绘制简单的图形化窗口

2、设置窗口属性

2.1 颜色设置

2.2 刷新

3、基本绘图函数

3.1 绘制直线

3.2 绘制圆

3.3 绘制矩形

4、贴图

4.1 原样贴图

4.1.1 IMAGE变量去表示图片

4.1.2 加载图片 

4.1.3 显示图片

4.2 透明贴图

4.2.1 认识素材

4.3 png贴图

5、按键交互

5.1 小球自由移动

5.2 按键控制小球

6、鼠标交互

1、绘制简单的图形化窗口

在之前,我们一运行程序会显示出来的黑框框是控制台窗口,现在,我们要绘制的是另一个窗口,即图形化窗口

首先需要包含头文件,这里有两个头文件可以使用,任意选择一个即可

1. graphics.h : 包含已经被淘汰的的函数

2. easyx.h : 只包含最新的函数

创建图形化窗口只需要两个函数:

1. 打开图形化窗口:initgraph(int x, int y, int style)

2. 关闭图形化窗口:closegraph()

在initgraph中,x和y是要创建的图形化窗口的大小,第三个参数是创建方式,若传入1则表示创建图形化窗口的同时还要创建控制台窗口,若不传或者传入的不是1,则表示只创建图形化窗口

打开完图形化窗口后一定记得要关闭图形化窗口 

void test_graph()
{initgraph(800, 600);while (1); // 为了防止一闪而过closegraph();
}

图形化窗口的坐标:

2、设置窗口属性

2.1 颜色设置

setbkcolor(颜色)

其中这面的颜色有两种形式传入

1. 颜色宏:既使用颜色英语的大写,这是编译器定义好的,可以在编译器内查看

即可查看可以使用的颜色

2. RGB配置

在电脑自带的画图当中,就可以找到一种颜色对应的RGB

所以我们此时可以写出这样的代码

void test_graph()
{initgraph(800, 600);setbkcolor(RED);while (1); // 为了防止一闪而过closegraph();
}

 但运行起来后会发现,图形化窗口仍然是黑色的,并没有变成设置的红色,这是为什么呢?

因为我们没有刷新

2.2 刷新

当我们设置完图形化窗口的颜色后,还需要刷新才能看到我们设置的颜色,否则仍然是initgraph打开的图形化窗口默认的黑色

void test_graph()
{initgraph(800, 600);setbkcolor(RED);cleardevice();while (1); // 为了防止一闪而过closegraph();
}

这样图形化窗口就变成了红色

3、基本绘图函数

3.1 绘制直线

line(int x, int y, int xx, int yy)

第一、二个参数是起点的坐标,第三、四个参数是终点的坐标

可以使用setlinecolor(颜色)来改变线的颜色

3.2 绘制圆

circle(int x, int y, int r)

第一、二个参数是圆心的坐标,第三个参数是半径

使用circle画出的圆是带线的,带线是指带边框线,并且圆内部的颜色是和图形化窗口的背景颜色相同的,若想要填充圆的颜色,需要使用下面的函数

填充圆,设置填充颜色:setfillcolor(颜色)

带线:fillcircle(int x, int y, int r)

不带线:solidcircle(int x, int y, int r)

注意:要填充圆的颜色只能使用下面这两个函数来画圆,不能使用circle

3.3 绘制矩形

rectangle(int x, int y, int xx, int yy)

第一、二个参数是矩形左上角的点的坐标,第三、四个参数是矩形右下角的点的坐标

填充矩形,设置填充颜色:setfillcolor(颜色)

带线:fillrectangle(int x, int y, int xx, int yy)

不带线:solidrectangle(int x, int y, int xx, int yy)

这里的规则与绘制圆中的规则是类似的,就不过多赘述了

void test_graph()
{initgraph(800, 600);setbkcolor(RED);cleardevice();line(0, 0, 800, 600);setfillcolor(BLUE);fillcircle(100, 100, 50);solidrectangle(200, 200, 300, 300);while (1); // 为了防止一闪而过closegraph();
}

我们可以使用刚刚学习的知识来绘制一个棋盘

void draw()
{initgraph(400, 400);for (int i = 0; i <= 400; i += 20){line(0, i, 400, i);line(i, 0, i, 400);}while (1);closegraph();
}

此时画出来的是黑底白线,也可以修饰一下

void draw()
{initgraph(400, 400);setbkcolor(BLUE);cleardevice();setlinecolor(BLACK);for (int i = 0; i <= 400; i += 20){line(0, i, 400, i);line(i, 0, i, 400);}while (1);closegraph();
}

此时就变成了蓝底黑线了

4、贴图

4.1 原样贴图

原样贴图就是将一张图片直接原封不动的贴到图形化窗口中

要使用原样贴图有三个步骤:

4.1.1 IMAGE变量去表示图片

图片是一个IMAGE类型的变量,类似于1是一个int类型的变量,所以可以int a = 1,用a来存储1

所以需要先创建一个IMAGE变量来存储图片

4.1.2 加载图片 

使用函数loadimage(IMAGE* img, URL, int width, int height)

第一个参数是指向图片的指针,传参时传的就是图片的地址,第二个参数是图片所在的路径(可以用相对路径,也可以用绝对路径),第三、四个参数可传可不传,不传是就是将图片原本的大小贴到图形化窗口中,若传了则可以修改图片在图形化窗口上的大小

4.1.3 显示图片

putimage(int x, int y, IMAGE* img)

第一、二个参数是图片左上角的坐标,第三个参数是指向图片的指针

此时演示一下。通常,我们会在.cpp的路径下创建一个文件夹,然后将相关资源放到这个文件夹里面,这里我们就可以将图片放到这个文件夹里面

编译器还要修改一下属性,修改成“使用多字节字符集”

void test_maps()
{initgraph(800, 600);IMAGE img;loadimage(&img, "./Res/qiqi.jpg");putimage(0, 0, &img);while (1); // 为了防止一闪而过closegraph();
}

此时会发现,图片太大了,设置的这个图形化窗口太小了,无法完全显示,所以我们可以设置图片的大小。缩放是为了解决图片大小与窗口大小不一致

void test_maps()
{initgraph(800, 600);IMAGE img;loadimage(&img, "./Res/qiqi.jpg", 800, 600);putimage(0, 0, &img);while (1); // 为了防止一闪而过closegraph();
}

此时就可以将图片完全显示了

4.2 透明贴图

当我们需要将两张图片放到同一个图形化窗口中时,其中一张作为背景图,另一张只需要一部分,此时会发现只需要一部分的那一张图片的一部分会遮挡住背景图

让第一张作为背景图,第二种放在其中

void test_maps()
{initgraph(800, 600);IMAGE img;loadimage(&img, "./Res/qiqi.jpg", 800, 600);putimage(0, 0, &img);IMAGE hz;loadimage(&hz, "./Res/hz.jpg",100,100);putimage(100, 100, &hz);while (1); // 为了防止一闪而过closegraph();
}

 

此时第二张图片的背景图也会影响第一张图片,那要如何才能去除第二张图片的背景图呢?

4.2.1 认识素材

首先,我们需要将第二章图片分别做成掩码图和背景图,利用PS

掩码图:想要显示的部分弄成黑色,不想显示的部分弄成白色

背景图:想要显示的部分不动,不想显示的部分弄成黑色

弄好了掩码图和背景图后,按照特定步骤贴图即可

SRCAND  贴掩码图

SRCPAINT  贴背景图   

要先贴掩码图,再贴背景图

void test_maps()
{initgraph(800, 600);IMAGE img;loadimage(&img, "./Res/qiqi.jpg", 800, 600);putimage(0, 0, &img);IMAGE test[2];loadimage(test + 0, "./Res/ym.jpg", 100, 100);loadimage(test + 1, "./Res/bj.jpg", 100, 100);putimage(100, 100, test + 0, SRCAND);putimage(100, 100, test + 1, SRCPAINT);while (1); // 为了防止一闪而过closegraph();
}

此时运行结果就是正常的

4.3 png贴图

#pragma once
#include<easyx.h>
// 把像素的颜色拆解出来
typedef struct _ARGB
{byte a;byte r;byte g;byte b;
}ARGB;
// 颜色拆解
ARGB color2Argb(DWORD c)
{ARGB res;res.r = (byte)c;res.g = (byte)(c >> 8);res.b = (byte)(c >> 16);res.a = (byte)(c >> 24);return res;
}
DWORD argb2Color(ARGB c)
{DWORD t = RGB(c.r, c.g, c.b);return ((DWORD)c.a) << 24 | t;
}
// 把彩色图转成黑白图
void toGray(IMAGE* src)
{DWORD* psrc = GetImageBuffer(src);for (int i = 0; i < src->getwidth() * src->getheight(); i++){// 获取每一个像素点的颜色值ARGB t = color2Argb(psrc[i]);// 灰度圈,求三个或者四个颜色值的均值byte arv = (t.r + t.g + t.b) / 3;ARGB res = { t.a,arv,arv,arv };psrc[i] = argb2Color(res);}
}
// @png透明贴图
void drawImg(int x, int y, IMAGE* src)
{// 变量初始化DWORD* pwin = GetImageBuffer();DWORD* psrc = GetImageBuffer(src);int win_w = getwidth();int win_h = getheight();int src_w = src->getwidth();int src_h = src->getheight();// 计算贴图的实际长度int real_w = (x + src_w > win_w) ? win_w - x : src_w;       // 处理超出右边界int real_h = (y + src_h > win_h) ? win_h - y : src_h;       // 处理超出下边界if (x < 0) { psrc += -x;           real_w -= -x; x = 0; }   // 处理超出左边界if (y < 0) { psrc += (src_w + -y); real_h -= -y; y = 0; }   // 处理超出上边界// 修正贴图起始位置pwin += (win_w * y + x);// 实现透明贴图for (int iy = 0; iy < real_h; iy++){for (int ix = 0; ix < real_w; ix++){byte a = (byte)(psrc[ix] >> 24);// 计算透明通道的值[0,256) 0为完全透明 255为完全不透明if (a > 100) pwin[ix] = psrc[ix];}// 换到下一行pwin += win_w;psrc += src_w;}
}

5、按键交互

案件交互分为阻塞按键交互和非阻塞按键交互

阻塞按键交互:不按按键时图片不会动

C语言中很多函数都是阻塞型的,如scanf,没有输入时程序就停止在哪里了

非阻塞按键交互:不按按键时图片可以动

接下来我们来实现两个案例

5.1 小球自由移动

struct Ball // 球的结构体
{int x;   // 球的横坐标int y;   // 球的纵坐标int r;   // 球的半径int dx;  // 球一次向x轴正方向移动的距离int dy;  // 球一次向y轴正方向移动的距离
};
struct Ball ball = { 400,400,15,5,-4 }; // 定义一个球
void DrawBall(struct Ball ball) // 画出球的函数
{setfillcolor(RED);solidcircle(ball.x, ball.y, ball.r);
}
void MoveBall() // 控制球移动的函数
{ball.x += ball.dx;ball.y += ball.dy;
}
int main()
{initgraph(800, 800);while (1){DrawBall(ball); // 首先画出一个球MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球Sleep(20); // 延时20ms}return 0;
}

但此时小球移动会有轨迹存在,所以在开始画出更新完状态之后的小球时,要先刷新

int main()
{initgraph(800, 800);while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球Sleep(20); // 延时20ms}return 0;
}

此时小球只会往一个方向移动,所以我们需要控制一下小球在碰撞到图形化窗口边界时,要反弹

void MoveBall() // 控制球移动的函数
{if (ball.x - ball.r <= 0 || ball.x + ball.r >= 800) { ball.dx = -ball.dx; }if (ball.y - ball.r <= 0 || ball.y + ball.r >= 800) { ball.dy = -ball.dy; }ball.x += ball.dx;ball.y += ball.dy;
}

5.2 按键控制小球

当用户按下按键时,也会产生一个值,可以用_getch()来获取,头文件是<conio.h>,然后根据这个值,来对小球做出处理

struct Ball // 球的结构体
{int x;   // 球的横坐标int y;   // 球的纵坐标int r;   // 球的半径int dx;  // 球一次向x轴正方向移动的距离int dy;  // 球一次向y轴正方向移动的距离
};
struct Ball ball = { 400,400,15,5,-4 }; // 定义一个球
void DrawBall(struct Ball ball) // 画出球的函数
{setfillcolor(RED);solidcircle(ball.x, ball.y, ball.r);
}
void MoveBall() // 控制球移动的函数
{if (ball.x - ball.r <= 0 || ball.x + ball.r >= 800) { ball.dx = -ball.dx; }if (ball.y - ball.r <= 0 || ball.y + ball.r >= 800) { ball.dy = -ball.dy; }ball.x += ball.dx;ball.y += ball.dy;
}
struct Ball myball = { 500,500,15,5,5 }; // 定义一个自己用按键控制的球,不调用MoveBall,而是自己用按键控制小球移动
void KeyDown() // 控制自己用按键控制的球的函数,通过接收按下的按键,来对小球的参数进行修改
{int userKey = _getch();switch (userKey){case 'w':case 'W':case '72': // 键盘上的方向键myball.y -= 5;break;case 's':case 'S':case '80': // 键盘上的方向键myball.y += 5;break;case 'a':case 'A':case '75': // 键盘上的方向键myball.x -= 5;break;case 'd':case 'D':case '77': // 键盘上的方向键myball.x += 5;break;}
}
void test_myball()
{initgraph(800, 800);while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球KeyDown();Sleep(20); // 延时20ms}closegraph();
}
int main()
{test_myball();return 0;
}

此时会发现,自己移动的小球也不动了,只有当我们按了按键让按键控制的球动了之后,自己移动的小球也会移动,一旦我们没按按键,自己移动的小球又停了

这是因为KeyDown函数中的_getch函数是阻塞型函数,当我们没有按按键时,程序会停止在这一步,循环无法继续,所以自己动的小球也不会继续走,这时候我们可以使用_kbhit()函数来判断我们是否按了按键,当我们按了按键,才会去走KeyDown

void test_myball()
{initgraph(800, 800);while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球if(_kbhit())KeyDown();Sleep(20); // 延时20ms}closegraph();
}

此时就正常了

玩过之后,会发现自己移动的小球移动起来不是很流畅,这是因为Sleep也是阻塞的,通常会使用定时器去控制自由移动的东西,而不使用Sleep

#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<time.h>
using namespace std;
struct Ball // 球的结构体
{int x;   // 球的横坐标int y;   // 球的纵坐标int r;   // 球的半径int dx;  // 球一次向x轴正方向移动的距离int dy;  // 球一次向y轴正方向移动的距离
};
struct Ball ball = { 400,400,15,5,-4 }; // 定义一个球
void DrawBall(struct Ball ball) // 画出球的函数
{setfillcolor(RED);solidcircle(ball.x, ball.y, ball.r);
}
void MoveBall() // 控制球移动的函数
{if (ball.x - ball.r <= 0 || ball.x + ball.r >= 800) { ball.dx = -ball.dx; }if (ball.y - ball.r <= 0 || ball.y + ball.r >= 800) { ball.dy = -ball.dy; }ball.x += ball.dx;ball.y += ball.dy;
}
struct Ball myball = { 500,500,15,5,5 }; // 定义一个自己用按键控制的球,不调用MoveBall,而是自己用按键控制小球移动
void KeyDown() // 控制自己用按键控制的球的函数,通过接收按下的按键,来对小球的参数进行修改
{int userKey = _getch();switch (userKey){case 'w':case 'W':case '72': // 键盘上的方向键myball.y -= 5;break;case 's':case 'S':case '80': // 键盘上的方向键myball.y += 5;break;case 'a':case 'A':case '75': // 键盘上的方向键myball.x -= 5;break;case 'd':case 'D':case '77': // 键盘上的方向键myball.x += 5;break;}
}
int Timer(int duration, int id)
{static int startTime[10]; // 创建10个定时器int endTime = clock();if (endTime - startTime[id] > duration){startTime[id] = endTime;return 1;}return 0;
}
void test_myball()
{initgraph(800, 800);while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);if(Timer(20,0))MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球if(_kbhit())KeyDown();// Sleep(20); // 延时20ms}closegraph();
}
int main()
{test_myball();return 0;
}

定时器的原理就是使用静态数组,因为静态变量只会初始化一次,所以每当函数调用时,数组中储存的还是上一次的值,并且静态数组不需要初始化,因为静态变量会被自动初始化为0。定时器的第一个参数是多少毫秒就需要让自己移动的小球移动一次,第二个参数是使用下标为id的定时器。clock()函数是基类程序运行到这里用了多长的时间,头文件是time.h。当程序运行到这里的时间减去选中的那个定时器的值大于给定的时间duration时,就表示自己移动的小球需要移动了,将下标为id的那个定时器的值改成clock()的结果,并返回1,表示需要移动。

为了不让用按键控制的小球一闪一闪的,还可以使用双缓冲绘图

开始双缓冲:BeginBatchDraw()

结束双缓冲:EndBatchDraw()

显示一帧:FlushBatchDraw()

void test_myball()
{initgraph(800, 800);BeginBatchDraw();while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);if(Timer(20,0))MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球if(_kbhit())KeyDown();// Sleep(20); // 延时20msFlushBatchDraw();}EndBatchDraw();closegraph();
}

因为_getch()是阻塞型的函数,所以在移动自己控制的小球时,会一卡一卡的,为了让小球更流畅,可以使用非阻塞型函数来接收按键的值
 

struct Ball // 球的结构体
{int x;   // 球的横坐标int y;   // 球的纵坐标int r;   // 球的半径int dx;  // 球一次向x轴正方向移动的距离int dy;  // 球一次向y轴正方向移动的距离
};
struct Ball ball = { 400,400,15,5,-4 }; // 定义一个球
void DrawBall(struct Ball ball) // 画出球的函数
{setfillcolor(RED);solidcircle(ball.x, ball.y, ball.r);
}
void MoveBall() // 控制球移动的函数
{if (ball.x - ball.r <= 0 || ball.x + ball.r >= 800) { ball.dx = -ball.dx; }if (ball.y - ball.r <= 0 || ball.y + ball.r >= 800) { ball.dy = -ball.dy; }ball.x += ball.dx;ball.y += ball.dy;
}
struct Ball myball = { 500,500,15,5,5 }; // 定义一个自己用按键控制的球,不调用MoveBall,而是自己用按键控制小球移动
void KeyDown() // 控制自己用按键控制的球的函数,通过接收按下的按键,来对小球的参数进行修改
{int userKey = _getch();switch (userKey){case 'w':case 'W':case '72': // 键盘上的方向键myball.y -= 5;break;case 's':case 'S':case '80': // 键盘上的方向键myball.y += 5;break;case 'a':case 'A':case '75': // 键盘上的方向键myball.x -= 5;break;case 'd':case 'D':case '77': // 键盘上的方向键myball.x += 5;break;}
}
void KeyDown2()
{if (GetAsyncKeyState(VK_UP))    { myball.y -= 5; }if (GetAsyncKeyState(VK_DOWN))  { myball.y += 5; }if (GetAsyncKeyState(VK_LEFT))  { myball.x -= 5; }if (GetAsyncKeyState(VK_RIGHT)) { myball.x += 5; }
}
int Timer(int duration, int id)
{static int startTime[10]; // 创建10个定时器int endTime = clock();if (endTime - startTime[id] > duration){startTime[id] = endTime;return 1;}return 0;
}
void test_myball()
{initgraph(800, 800);BeginBatchDraw();while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);if(Timer(20,0))MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球/*if(_kbhit())KeyDown();*/KeyDown2();// Sleep(20); // 延时20msFlushBatchDraw();}EndBatchDraw();closegraph();
}
int main()
{test_myball();return 0;
}

用KeyDown2来替代KeyDown,并且因为是非阻塞型的,所以可以不需要if(_kbhit())来判断了

但此时自己控制的小球会移动的非常快,为了让小球速度正常,可以使用定时器

void test_myball()
{initgraph(800, 800);BeginBatchDraw();while (1){cleardevice(); // 刷新DrawBall(ball); // 首先画出一个球DrawBall(myball);if(Timer(20,0))MoveBall(); // 移动完成后更新了小球的状态,等待下一次进入循环后打印出新状态的小球/*if(_kbhit())KeyDown();*/if(Timer(20,1))KeyDown2();// Sleep(20); // 延时20msFlushBatchDraw();}EndBatchDraw();closegraph();
}

此时使用的是下标为1的定时器

6、鼠标交互

当用户点击鼠标的按键时,就会产生一个值,类型是ExMessage,称为鼠标消息,鼠标消息实际上是一个结构体

获取鼠标消息peekmessage(&变量)

讨论鼠标消息 

msg.message:区分鼠标消息的类型,用户按下的值存储在结构体变量msg的message中

msg.x   msg.y: 鼠标当前的坐标

 

void test_mouse()
{initgraph(800, 800);ExMessage msg;// 按左键画圆,按右键画矩形while (1){while (peekmessage(&msg)){switch(msg.message) // 根据用户按下的按键,判断在当前鼠标位置画哪一个{case WM_LBUTTONDOWN:circle(msg.x, msg.y, 30);break;case WM_RBUTTONDOWN:rectangle(msg.x - 10, msg.y - 10, msg.x + 10, msg.y + 10);break;}}}closegraph();
}
int main()
{test_mouse();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Redission分布式锁-源码解析(手把手解析)

文章目录 1.关于锁的重试机制&#xff1a;2.锁的超时问题 1.关于锁的重试机制&#xff1a; 进一步进入tryLock函数内部 2.锁的超时问题 加入目前获取锁成功了&#xff0c;我有一个剩余的有效期&#xff0c;万一业务阻塞了&#xff0c;TTL到期了&#xff0c;其他线程又进来拿锁…

[数据结构] 基于交换的排序 冒泡排序快速排序

标题&#xff1a;[数据结构] 基于交换的排序 冒泡排序&&快速排序 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 &#xff08;一&#xff09;冒泡排序 优化后实现&#xff1a; &#xff08;二&#xff09;快速排序 I、实现方法&#xff1a; &#…

移动应用开发课设——原神小助手文档(1)

2023年末&#xff0c;做的移动应用开发课设&#xff0c;分还算高&#xff0c;项目地址&#xff1a;有帮助的话&#xff0c;点个赞和星呗~ GitHub - blhqwjs/-GenShin_imp: 2023年移动应用开发课设 本文按照毕业论文要求来写&#xff0c;希望对大家有所帮助。 xxxx大学课程设计报…

一级指针 二级指针

目录 一级指针 二级指针 通过二级指针打印原数据 一级指针 一级指针就是存放变量的指针 代码演示&#xff1a; #include<stdio.h> int main() {int a 10;int* pa &a;return 0; } pa就是一级指针变量&#xff0c;是变量就会有地址&#xff0c;因为变量都是在…

警惕AI泡沫:巨额投资与回报失衡

尽管高科技巨头们在AI基础设施上投入巨资&#xff0c;但AI带来的收入增长尚未显现&#xff0c;揭示了生态系统末端用户价值的重大缺口。 红杉资本分析师David Cahn认为&#xff0c;AI企业需每年赚取约6000亿美元才能抵消其AI基础设施&#xff08;如数据中心&#xff09;的成本&…

Docker部署Seata与Nacos整合

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Docker部署Seata与Nacos整合 Docker 部署 Seata 与 Nacos 整合 运行所使用的 demo项目地址 …

测试环境:使用OpenSSL生成证书并配置Https

文章目录 需求1、安装OpenSSL1.1、安装包下载1.2、安装&#xff08;以window 64位为例&#xff09;1.3、配置环境变量&#xff08;非必须&#xff09; 2、生成证书2.1、新建文件夹2.2、生成根证书2.2.1、生成私钥2.2.2、生成根证书&#xff0c;并且自签名 2.3、服务端证书生成2…

自然之美无需雕琢

《自然之美&#xff0c;无需雕琢 ”》在这个颜值至上的时代&#xff0c;但在温馨氛围中&#xff0c;单依纯以一种意想不到的方式&#xff0c;为我们诠释了自然之美的真谛。而医生的回答&#xff0c;如同一股清流耳目一新。“我说医生你看我这张脸&#xff0c;有没有哪里要动的。…

论文回顾 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法

论文速览 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法 1 引言 在计算机视觉和机器人领域,相机校准一直是一个基础而又重要的问题。传统的相机校准方法主要依赖于从已知校准图案中提取角点,然后通过优化算法求解相机的内参和外参。这…

绝区叁--如何在移动设备上本地运行LLM

随着大型语言模型 (LLM)&#xff08;例如Llama 2和Llama 3&#xff09;不断突破人工智能的界限&#xff0c;它们正在改变我们与周围技术的互动方式。这些模型早已集成到我们的手机中&#xff0c;但到目前为止&#xff0c;它们理解和处理请求的能力还非常有限。然而&#xff0c;…

认识并理解webSocket

今天逛牛客&#xff0c;看到有大佬分享说前端面试的时候遇到了关于webSocket的问题&#xff0c;一看自己都没见过这个知识点&#xff0c;赶紧学习一下&#xff0c;在此记录&#xff01; WebSocket 是一种网络通信协议&#xff0c;提供了全双工通信渠道&#xff0c;即客户端和服…

TeXstudio对已加载宏包的命令标记为暗红色未知命令

宏包已正常加载&#xff0c;编译也正常&#xff0c;但却将某些命令标记为暗红色。 具体的原因可参考 https://sourceforge.net/p/texstudio/wiki/Frequently%20Asked%20Questions/#how-does-txs-know-about-valid-commandshttps://sourceforge.net/p/texstudio/wiki/Frequent…

非对称加密算法原理与应用2——RSA私钥加密文件

作者:私语茶馆 1.相关章节 (1)非对称加密算法原理与应用1——秘钥的生成-CSDN博客 第一章节讲述的是创建秘钥对,并将公钥和私钥导出为文件格式存储。 本章节继续讲如何利用私钥加密内容,包括从密钥库或文件中读取私钥,并用RSA算法加密文件和String。 2.私钥加密的概述…

【HICE】转发服务器实验

1.在本地主机上操作 2.在客户端操作设置主机的IP地址为dns 3.测试,客户机是否能ping通

Micron近期发布了32Gb DDR5 DRAM

Micron Technology近期发布了一项内存技术的重大突破——一款32Gb DDR5 DRAM芯片&#xff0c;这项创新不仅将存储容量翻倍&#xff0c;还显著提升了针对人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&#xff09;、高性能计算&#xff08;HPC&#xff09;以及数…

转发服务器实验

首先先克隆一个虚拟机并完成ip地址的修改 nmcli connection modify ens160 ipv4.addresses 192.168.209.128/24 nmcli connection modify ens160 ipv4.method manual nmcli connection modify ens160 connection.autoconnect yes nmcli connection up ens160 nmcli connection…

基于深度学习LightWeight的人体姿态检测跌倒系统源码

一. LightWeight概述 light weight openpose是openpose的简化版本&#xff0c;使用了openpose的大体流程。 Light weight openpose和openpose的区别是&#xff1a; a 前者使用的是Mobilenet V1&#xff08;到conv5_5&#xff09;&#xff0c;后者使用的是Vgg19&#xff08;前10…

昇思25天学习打卡营第11天|MindSpore 助力下的 GPT2:数据集加载处理及模型全攻略

目录 环境配置 数据集下载和获取 数据集拆分 处理数据集 模型构建 ​​​​​​​模型训练 ​​​​​​​模型推理 环境配置 “%%capture captured_output”这一行指令通常旨在捕获后续整个代码块所产生的输出结果。首先&#xff0c;将已预装的 mindspore 库予以卸载。随后&a…

2024年AI技术深入研究

2024年AI技术持续快速发展,应用领域广泛,产业发展迅速,市场趋势积极,学术研究深入。 AI技术进展大模型发展 2024年,智谱AI正在研发对标OpenAI Sora的高质量文生视频模型,预计最快年内发布。智谱AI的进展显示了国内AI大模型领域的快速发展,以及与国际领先技术的竞争态势…

Ubuntu20.04突然没网的一种解决办法

本来要学一下点云地图处理&#xff0c;用octomap库&#xff0c;但是提示少了octomap-server库&#xff0c;然后通过下面命令安装的时候&#xff1a; sudo apt install ros-noetic-octomap-server 提示&#xff1a;错误:7 https://mirrors.ustc.edu.cn/ubuntu focal-security …