「Qt」常用事件介绍

        🔔 在开始本文的学习之前,笔者希望读者已经阅读过《「Qt」事件概念》这篇文章了。本文会在上篇文章的基础上,进一步介绍 Qt 中一些比较常用的事件。

0、引言

        当我们想要让控件收到某个事件时做一些操作,通常都需要重写相应的事件处理函数。这些事件处理函数本质上就是普通的成员函数,并且是受保护的虚函数以便子类访问并做可能的重写。我们只需要继承控件类并重写相应的事件处理函数就行了。

        在上篇文章中我们已经大致介绍过了 QAbstractButton 类的鼠标事件了,本文就不再赘述了,接下来再介绍一些其他事件。

1、定时器事件

        定时器事件是由程序产生的 Qt 事件,定时器事件处理函数源自于 QObject 类的一个受保护的虚函数。

void QObject::timerEvent(QTimerEvent *event)       //[virtual protected]/*可以在子类中重写该事件处理器以让其对象接收定时器事件,定时器事件在事件参数中传递*/

定时器事件通常的使用场景就是当我们需要计时的时候使用,比如我们想做一个简单的秒表可以实现显示的数字每隔一秒加一。一个比较简单的实现方案就是使用 QLabel 类作为数字显示的控件,启动一个定时器并在定时器事件处理函数中让其显示的数字加一即可。


        首先是启动一个定时器,在 Qt 中我们可以 使用 QTimer 类来创建和管理定时器(推荐) 或者 使用 QObject 类的 startTimer() 方法启动定时器

  1. 使用 QTimer 类(推荐),下面是一个简单代码演示:
    #include <QTimer>class MyClass : public QObject
    ...QTimer *timer = new QTimer(this);    //创建定时器对象
    timer->setInterval(1000);            //设置时间间隔为1000毫秒
    connect(timer, &QTimer::timeout, this, &MyClass::onTimeout);
    timer->start();                      //启动定时器

            QTimer为定时器功能提供了更高级别的接口(信号接口),还提供了关于定时器的更一般的信息。对于上面的演示代码我们可以看到 QTimer 类是提供了专门的信号timeout())来通知其他对象计时到达的,该类继承自 QObject 类并重写了父类的 timerEvent() 事件处理函数。由此我们可以很容易想到:其实 QTimer 类的 timeout() 信号就是在它重写的 timerEvent() 事件处理函数中发出的

            此外,QTimer::start() 与 QTimer::stop() 配合 QLabel 显示数字使用还可以达到暂停与继续计时的功能。具体实现很简单笔者就不展开讲了~

  2. 使用 QObject::startTimer() 方法创建定时器,下面是一个简单代码演示:
    /*** mainwindow.h ***/#ifndef MAINWINDOW_H
    #define MAINWINDOW_H#include <QMainWindow>...protected://重写定时器事件处理函数virtual void timerEvent(QTimerEvent *event);private://声明一个整型用于表示计时时间int timeNum;
    ...
    /*** mainwindow.cpp ***/#include "mainwindow.h"
    #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), timeNum(0)
    {ui->setupUi(this);//启动定时器this->startTimer(1000);     //参数为时间间隔(ms)
    }void MainWindow::timerEvent(QTimerEvent *event)
    {ui->label->setNum(timeNum);timeNum++;
    }MainWindow::~MainWindow()
    {delete ui;
    }

        下面是 startTimer() 方法的原型:

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)

        启动一个定时器(叫“计时器”也可以)并返回一个定时器标识符,如果无法启动则返回零。

        一个定时器事件每隔 interval 毫秒就会发生一次直到 killTimer() 被调用。如果 interval 被设置为 0,则每次没有更多要处理的窗口系统事件时,计时器事件都会发生一次。

        发生定时器事件时,将使用 QTimerEvent 事件参数类调用虚 timerEvent() 函数,重写此函数以获取定时器事件。

        如果有多个定时器正在运行,可以使用 QTimerEvent::timerId() 找到哪个定时器处于激活状态。


        在上一篇文章介绍 事件分发 —— event()函数 时,提到过“鼠标按下事件发生时会根据鼠标的位置和控件的几何形状来判断这个事件应该派发给哪个控件接收。”;而定时器事件作为由程序产生的 Qt 事件,接收并处理事件的依据是:哪个类的对象调用了自己的 startTimer() 方法启动定时器,与启动定时器的对象具有相同线程的该对象的 timerEvent() 函数就会接收到自己的定时器事件!

        在上面的代码例中,原本定时器事件的接收对象应该是那个 label 对象(毕竟我们是要让 label 显示的数字加一嘛),不过由于我们可以通过用户界面(User Interface)对象的指针访问到界面元素(ui->label),所以我们可以在 MainWindow 中启动定时器并重写 MainWindow 类的定时器事件处理函数。这样做的好处是可以避免去继承 QLabel 类并重写它的定时器事件处理函数,省去了很多麻烦

        如果有多个定时器正在运行的情况,使用 QTimerEvent::timerId() 找到是哪个定时器触发了事件。下面是一个简单的代码例演示了一个 1秒1次的定时器 和一个 2秒1次的定时器 同时运行的情况:

/*** mainwindow.h ***/#ifndef MAINWINDOW_H
#define MAINWINDOW_H...protected:virtual void timerEvent(QTimerEvent *event);private:Ui::MainWindow *ui;int timeNum;         //声明一个整型保存秒表显示的值int timeNum2;int firstTimerId;    //声明一个整型保存第一个定时器的标识符int secondTimerId;...
/*** mainwindow.cpp ***/#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), timeNum(1), timeNum2(1)
{ui->setupUi(this);firstTimerId = this->startTimer(1000);    //1秒1次定时器secondTimerId = this->startTimer(2000);   //2秒1次定时器
}/*** @brief 重写定时器事件处理函数:根据定时器标识符做不同处理*/
void MainWindow::timerEvent(QTimerEvent *event)
{//使用事件对象的timerId()函数判断触发定时器事件的是哪个定时器if(event->timerId() == firstTimerId){ui->label->setNum(timeNum);timeNum++;}if(event->timerId() == secondTimerId){ui->label_2->setNum(timeNum2);timeNum2++;}
}MainWindow::~MainWindow()
{delete ui;
}

运行效果:

2、绘图事件

        与绘图事件相关的主要有三个类和函数:QPaintEvent 绘图事件类、QPainter 绘制图形类与 paintEvent(QPaintEvent *event) 绘图事件处理函数。其中 QPainter 通常与 QPenQBrush 一起使用,分别用于定义绘制图形的轮廓线和填充样式。下面是一个简单的代码例:

/*** mainwindow.h ***/#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPainter>
#include <QDebug>...protected://重写绘图事件处理函数void paintEvent(QPaintEvent *e);private:Ui::MainWindow *ui;int count;      //使用一个成员变量记录打印次数...
/*** mainwindow.cpp ***/#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), count(1)
{ui->setupUi(this);
}/*** @brief 重写绘图事件处理函数*/
void MainWindow::paintEvent(QPaintEvent *e)
{//实例化一个 QPainter 对象并指定绘图设备为当前对象(this)QPainter painter(this);            //QPainter 类大多是在 paintEvent() 绘图事件处理函数中使用的//设置画笔颜色为红色QPen pen(QColor(255, 0, 0));//设置画笔宽度为3个像素pen.setWidth(3);//设置画笔风格为破折点线pen.setStyle(Qt::DashDotLine);painter.setPen(pen);//利用画刷为封闭图形填充颜色(渐变色)QGradient gradient(QGradient::NewYork);//为 QPainter 对象设置画刷后,会自动为其绘制的所有封闭图形填充颜色painter.setBrush(gradient);//从(0,0)到(100,100)画一条线painter.drawLine(QPoint(0, 0), QPoint(100, 100));//以(100,100)为圆心画一个长半轴为100,短半轴为50的椭圆painter.drawEllipse(QPoint(100, 100), 100, 50);//画一个左上角为(20,20),右下角为(50,50)的矩形painter.drawRect(QRect(QPoint(20, 20), QPoint(50, 50)));//绘制文字painter.drawText(QRect(10,200,150,50), "测试绘图文字");//打印调用次数qDebug() << QString("调用%1次绘图事件处理函数").arg(count);
}MainWindow::~MainWindow()
{delete ui;
}

运行效果:

        可以看到,绘图事件的产生是不需要我们手动去触发的(像“鼠标按下”这类事件是需要我们手动按下鼠标才会产生事件的)。实际上,当发生以下情况时会产生绘图事件并调用 paintEvent() 绘图事件处理函数:

  1. 在窗口部件第一次显示时,系统会自动产生一个绘图事件,从而强制绘制这个窗口部件;
  2. 当重新调整窗口部件的大小时,系统也会产生一个绘制事件;

  3. 当窗口部件被其他窗口部件遮挡,然后又再次显示出来的时候,就会对哪些隐藏的区域产生绘图事件;

有关 QBrush 类的更多信息,可以参考这里;

2.1、QPainter 类的高级设置

不多说直接上代码(修改的上面代码中的绘图事件处理函数):

void MainWindow::paintEvent(QPaintEvent *e)
{QPainter painter(this);painter.drawEllipse(QPoint(400, 50), 50, 50);   //以(400,50)为圆心画一个半径为50的圆//设置抗锯齿painter.setRenderHint(QPainter::Antialiasing);painter.drawEllipse(QPoint(500, 50), 50, 50);   //在抗锯齿渲染下以(500,50)为圆心画一个半径为50的圆//保存 painter 状态(将状态入栈)。save() 后面必须跟上相应的 restore();end() 函数展开堆栈painter.save();painter.drawRect(QRect(75, 150, 50, 50));       //画一个左上角为(75,150),宽50,高50的矩形//坐标系移动指定偏移量painter.translate(100, 100);painter.drawRect(QRect(75, 150, 50, 50));       //坐标系沿x和y正半轴分别平移100个像素后画一个左上角为(75,150),宽50,高50的矩形/*** 以下为绘制的标注,无需了解 ***///还原 painter 状态painter.restore();QPen pen(QColor(255, 0, 0));pen.setStyle(Qt::DashLine);painter.setPen(pen);painter.drawText(QRect(385, 100, 150, 50), "无抗锯齿 vs 抗锯齿");painter.drawLine(QPoint(0, 150), QPoint(75, 150));painter.drawLine(QPoint(75, 0), QPoint(75, 150));painter.drawLine(QPoint(0, 250), QPoint(175, 250));painter.drawLine(QPoint(175, 0), QPoint(175, 250));painter.drawText(QRect(10, 152, 150, 50), "75像素");painter.drawText(QRect(77, 60, 150, 50), "150像素");painter.drawText(QRect(60, 252, 150, 50), "175像素");painter.drawText(QRect(177, 110, 150, 50), "250像素");painter.drawText(QRect(65, 310, 150, 50), "坐标系平移效果");
}

运行效果:

我们还可以使用 QPainter 类直接绘制图片:

🔔 绘制图片的前提是您已经将图片资源添加到项目当中了。

//假设项目中已经添加了一个名为“prompt”的图形资源文件void MainWindow::paintEvent(QPaintEvent *e)
{QPainter painter(this);painter.drawPixmap(20,100,QPixmap(":/prompt.svg"));    //在 (20, 100) 处绘制一张图片
}

运行效果:

2.2、手动调用绘图事件

        在某些情况下,我们可能想要手动调用绘图事件。通常可以在需要的地方主动调用如下两个方法以手动调用绘图事件:repaint() 方法(已过时)和 update() 方法(推荐)

当然,我们主动调用了哪个对象的 update() 方法,那个对象的绘图事件就会触发。

3、绘图与绘图设备

3.1、Qt 绘图系统

        Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于 QPainterQPaintEngineQPaintDevice 三个类。

Qt绘图系统

        QPainter 用于执行绘图的操作;QPaintDevice 是一个二维空间的抽象,允许 QPainter 在其上面进行绘制,也就是 QPainter 工作的空间。QPaintEngine 提供了 QPainter 在不同的设备上进行绘制的统一的接口。QPaintEngine 类应用于 QPainter 和 QPaintDevice 之间,通常我们无需关心(除非我们要自定义绘图设备)。参考现实生活,QPainter 可以看作是画笔,QPaintDevice 可以看作是纸张或者数位板;使用 QPainter 在 QPaintDevice 上进行绘制,它们之间的交互依赖于 QPaintEngine。

3.2、绘图设备

绘图设备 是指继承自 QPainterDevice 的子类,包含:QPixmapQBitmapQImageQPicture等。

  • QPixmap:离屏图像表示,可以用作绘图设备;设计用于图像在屏幕上显示的优化。
  • QBitmap:继承自 QPixmap,专用于提供单色(1 位深度)的 QPixmap。
  • QImage:硬件无关的图像表示形式,允许直接访问像素数据,专门为 I/O 和直接像素访问的操作做了优化。
  • QPicture:记录并重放 QPainter 命令。它将 QPainter 命令序列化到一个 IO 设备中,保存为一个平台独立的文件格式。

3.2.1、QPixmap

        QPixmap 继承了 QPaintDevice,可以直接使用 QPainter 在上面绘制图形。QPixmap 也可以接受一个文件路径字符串显示图像。使用 QPainter 的 drawPixmap() 函数可以把一个 QPixmap 绘制到一个 QLabel、QPushButton 或者其他设备上(参考文本 2.1 小节最后面)。

        QPixmap 设计为图像在屏幕上的显示做了优化,因此其与实际的底层显示设备息息相关。注意,这里说的“显示设备”是指操作系统提供的原生绘图引擎。所以,在不同的操作系统平台下,QPixmap 的显示可能会有所差别。

        下面是一个使用 QPixmap 绘图的简单代码示例:

/*** mainwindow.h ***/#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPixmap>
#include <QPainter>
#include <QDir>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
/*** mainwindow.cpp ***/#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//QPixmap 绘图设备,画布大小为 300*300QPixmap pixmap(300, 300);//使用白色填充整个绘图设备//pixmap.fill(Qt::white);//实例化一个 QPainter 对象并指定绘图设备为 QPixmap 对象QPainter painter(&pixmap);//设置画笔颜色为绿色painter.setPen(QPen(Qt::green));//以(150,150)为圆心画一个半径为 100 的圆painter.drawEllipse(QPoint(150, 150), 100, 100);//保存 QPixmap 到用户根目录pixmap.save(QDir::homePath() + "/MySql.png");
}MainWindow::~MainWindow()
{delete ui;
}

运行这段代码后,可以看到用户根目录保存了该绘图:

保存 QPixmap

3.2.2、QImage

        QImage 继承了 QPaintDevice,可以直接使用 QPainter 在上面绘制图形。代码示例与上一节代码基本一致。仅仅是声明的绘图设备有所变化:

//QImage 绘图设备,画布大小为 300*300,格式为 ARGB32
QImage image(300, 300, QImage::Format_ARGB32);

        两者的区别在于:当绘图设备没有填充颜色时,QPixmap 保存的 png 图片默认为黑色背景;而 QImage 保存的 png 图片默认为无背景

保存图像对比

        此外,我们在上面提到过“QImage 允许直接访问像素数据”(比如使用 setPixel() 方法)。下面是一个相关代码示例:

/*** mainwindow.h ***/#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QImage>
#include <QPainter>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();protected://重写绘图事件处理函数void paintEvent(QPaintEvent *event);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
/*** mainwindow.cpp ***/#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}/*** @brief 重写绘图事件处理函数*/
void MainWindow::paintEvent(QPaintEvent *event)
{//实例化一个 QPainter 对象并指定绘图设备为当前窗口QPainter painter(this);//利用 QImge 进行像素访问的操作QImage img;img.load("://resources/prompt.svg");//修改像素点for(int i = 50; i < 100; i++){for(int j = 50; j < 100; j++){//设置像素img.setPixel(i, j, qRgb(255, 0, 0));}}painter.drawImage(0, 0, img);
}MainWindow::~MainWindow()
{delete ui;
}

运行效果:

QImage 访问像素

3.2.3、QPicture

        QPicture 用于记录并重放 QPainter 命令(相关方法有 save()load()play() )。下面是一个简单的使用方法代码示例:

/*** mainwindow.h ***/#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPicture>
#include <QDir>
#include <QPainter>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();protected://重写绘图事件处理函数void paintEvent(QPaintEvent *event);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
/*** mainwindow.cpp ***/#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//QPicture 绘图设备,可以记录并重放 QPainter 命令QPicture picture;//实例化一个 QPainter 对象QPainter painter;//使用 begin() 方法指定 QPainter 对象的绘图设备painter.begin(&picture);//设置画笔颜色为绿色painter.setPen(QPen(Qt::blue));//以(150,150)为圆心画一个半径为 100 的圆painter.drawEllipse(QPoint(150, 150), 100, 100);//结束绘制painter.end();//保存 QPicture 到用户根目录(存储的文件后缀可以任意,不一定是 .txt)picture.save(QDir::homePath() + "/picture.txt");
}/*** @brief 重写绘图事件处理函数*/
void MainWindow::paintEvent(QPaintEvent *event)
{//开始重放 QPainter 命令QPicture picture;//从保存的文件中加载 QPainter 命令picture.load(QDir::homePath() + "/picture.txt");//实例化一个 QPainter 对象并指定绘图设备为当前窗口QPainter painter(this);//在(0,0)处绘制图像painter.drawPicture(0, 0, picture);
}MainWindow::~MainWindow()
{delete ui;
}

运行效果:

QPicture 记录并重放 QPainter 命令

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

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

相关文章

Arthas GC日志-JVM(十八)

上篇文章说jvm的实际运行情况。 Jvm实际运行情况-JVM&#xff08;十七&#xff09; Arthas介绍 因为arthas完全是java代码写的&#xff0c;我们直接用命令启动&#xff1a; Java -jar arthas-boot.jar 启动成功后&#xff0c;选择我们项目的进程。 进入我们可用dashboard…

接口测试python练习

单元测试框架unittest 优点&#xff1a; ①批量执行用例 ②自带断言功能 ③借助插件生成测试报告 &#xff08;测试报告插件有很多&#xff1a;HTMLTestRunner&#xff09;Allure测试报告&#xff08;长得很好看&#xff09; 注意&#xff1a; 现在比较流行的还有pytest&…

【Ansible 的脚本 --- playbook 剧本】

目录 一、playbook 剧本介绍二、示例1、运行playbook2、定义、引用变量 三、使用playbook部署lnmp集群 一、playbook 剧本介绍 playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在…

【移动机器人运动规划】02 —— 基于采样的规划算法

文章目录 前言相关代码整理:相关文章&#xff1a; 基本概念概率路线图&#xff08;Probabilistic Road Map&#xff09;基本流程预处理阶段查询阶段 优缺点&#xff08;pros&cons&#xff09;一些改进算法Lazy collision-checking Rapidly-exploring Random Tree算法伪代码…

2023华数杯数学建模C题母亲对婴儿影响论文完整讲解

大家好呀&#xff0c;从昨天发布赛题一直到现在&#xff0c;总算完成了华数杯数学建模C题完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 C题论文共72页&#xff0c;一些修改说…

iOS——Block two

Block 的实质究竟是什么呢&#xff1f;类型&#xff1f;变量&#xff1f;还是什么黑科技&#xff1f; Blocks 是 带有局部变量的匿名函数 Blocks 由 OC 转 C 源码方法 在项目中添加 blocks.m 文件&#xff0c;并写好 block 的相关代码。打开「终端」&#xff0c;执行 cd XX…

LNMP安装

目录 1、LNMP简述&#xff1a; 1.1、概述 1.2、LNMP是一个缩写词&#xff0c;及每个字母的含义 1.3、编译安装与yum安装差异 1.4、编译安装的优点 2、通过LNMP创建论坛 2.1、 安装nginx服务 2.1.1、关闭防火墙 2.1.2、创建运行用户 2.1.3、 编译安装 2.1.4、 优化路…

前端JS实用操作符,一些骚操作✨

目录 0、!! 双重逻辑非操作符 &#x1f4da; 1、?? 操作符 空值合并/空判断 ✅ 2、?. 可选链运算符&#x1f50d; 3、?? 操作符 逻辑空值赋值运算符 &#x1f49a; 4、三元运算符 &#x1f4d7; 5、~~ 操作符 双位运算符 &#x1f528; 6、&&与 ||或 短…

【Autolayout自动布局介绍 Objective-C语言】

一、好,我们开始介绍Autolayout 1.什么事Autolayout 好,那么,接下来,我们介绍一下这个Autolayout Autolayout,就是“自动布局” 那么,自动布局,它就是专门用来做UI界面的 那么,UI界面,我们为了适应不同屏幕,要进行自动布局, 所以要使用Autolayout 这个Autolayou…

Open3D (C++) 计算矩阵的广义逆

目录 一、算法原理1、广义逆2、计算过程二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人,爬些不完整的误导别人有意思吗???? 一、算法原理 1、广义逆 非方阵不存在逆,但是存在广义逆(伪逆)。对于一个矩阵

数据仓库设计理论

数据仓库设计理论 一、数据仓库基本概念 1.1、数据仓库介绍 数据仓库是一个用于集成、存储和分析大量结构化和非结构化数据的中心化数据存储系统。它旨在支持企业的决策制定和业务分析活动。 1.2、基本特征 主题导向&#xff1a;数据仓库围绕特定的主题或业务领域进行建模…

【网络基础实战之路】基于MGRE多点协议的实战详解

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 PS&#xff1a;本要求基于…

记录一次Linux环境下遇到“段错误核心已转储”然后利用core文件解决问题的过程

参考Linux 下Coredump分析与配置 在做项目的时候&#xff0c;很容易遇到“段错误&#xff08;核心已转储&#xff09;”的问题。如果是语法错误还可以很快排查出来问题&#xff0c;但是碰到coredump就没办法直接找到问题&#xff0c;可以通过设置core文件来查找问题&#xff0…

About Multiple regression

ps:this article is not very strict,just some ml and mathematic basic knowledge.My english is poor too.So If this passage make you confuse and uncomfortable.Please give me a feedback in the comment :-D Prior to this(在此之前), we learned the concept of sin…

数据结构:单链表的实现(C语言)

个人主页 &#xff1a; 水月梦镜花 个人专栏 &#xff1a; 《C语言》 《数据结构》 文章目录 前言一、单链表实现思路和图解1.节点的定义(SListNode)2.申请一个节点(BuySListNode)3.单链表打印(SListPrint)4.单链表尾插(SListPushBack)5.单链表的头插(SListPushFront)6.单链表的…

vue2-v-show和v-if有什么区别,使用场景分别是什么?

1、v-show和v-if的共同点 在vue中&#xff0c;v-if和v-show的作用效果是相同的&#xff08;不含v-else&#xff09;&#xff0c;都能控制元素在页面是否显示&#xff0c;在用法上也相同。 当表达式为true的时候&#xff0c;都会占据页面的位置 当表达式为false的时候&#xff…

css3 hover border 流动效果

/* Hover 边线流动 */.hoverDrawLine {border: 0 !important;position: relative;border-radius: 5px;--border-color: #60daaa; } .hoverDrawLine::before, .hoverDrawLine::after {box-sizing: border-box;content: ;position: absolute;border: 2px solid transparent;borde…

TCP的三次握手和四次挥手······详解

1、三次握手 三次握手是建立连接的过程 如图大致为三次握手的流程图&#xff1a; 当客户端对服务端发起连接时&#xff0c;会先发一个包连接请求数据&#xff0c;去询问能否建立连接&#xff0c;该数据包称为 “SYN”包 然后&#xff0c;如果对方同意连接&#xff0c;那么…

九耶|阁瑞钛伦特 Java中,锁的实现方式

在Java中&#xff0c;锁的实现方式有以下几种&#xff1a; 1. Synchronized关键字&#xff1a;使用synchronized关键字可以创建一个互斥锁&#xff0c;它可以保证同一时刻只有一个线程可以进入被synchronized关键字修饰的代码块或方法。 2. ReentrantLock类&#xff1a;Reentr…

二叉树进阶版(C)

文章目录 1.树1.1概念1.2相关定义1.3 表示&#xff08;左孩子右兄弟&#xff09; 2.二叉树2.1概念2.2特殊的二叉树1. 满二叉树&#xff1a;2. 完全二叉树&#xff1a; 2.3二叉树的性质2.4练习 3.二叉树的存储结构1. 顺序存储2. 链式存储 4.完全二叉树的代码实现4.1堆的介绍1.堆…