<Qt> 系统 - 事件

news2024/12/22 22:37:53

目录

前言:

一、事件介绍

二、事件的处理

(一)鼠标事件

1. 进入和离开事件

2. 鼠标点击事件

3. 释放事件

4. 双击事件

5. 移动事件

6. 滚轮事件

(二)键盘按键事件

1. 单个按键

2. 组合按键

(三)定时器

1. QTimerEvent 

2. QTimer

(四)窗口事件

三、事件分发器

(一)事件分发器工作原理

四、事件过滤器


前言:

在信号和槽章节中,我们了解到用户进行的操作可能会产生某种信号,给一个信号连接上槽函数,当信号触发的时候,就可以执行对应的槽函数,进而完成各种功能。除了信号,用户进行的操作也会产生事件,我们也可以给事件关联上处理函数,当事件触发的时候,就可以执行对应的代码。

这么一看,事件和信号还是差不多的,事件本身是操作系统提供的机制,Qt 把操作系统的事件机制进行封装,但是事件的代码编写起来不是很方便,所以 Qt 对于事件进一步封装,这就是信号和槽,事件就是它的底层机制。

实际 Qt 开发过程中,多数的交互功能都是通过信号和槽来完成的,但是也有特殊的情况,信号和槽无法实现,就比如 Qt 中没有这个信号,这就需要重写事件处理函数,来手动处理事件的逻辑。

一、事件介绍

事件应用程序或者外部的事情或者动作的统称。在Qt平台中使用一个对象来表示一个事件所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在用户操作时发出,如键盘事件、鼠标事件等,另一些事件则是由系统本身自动发出,如定时器事件。常见的Qt事件如下:

常见的 Qt 事件如下: 

事件名称描述
⿏标事件⿏标左键、⿏标右键、⿏标滚轮,⿏标的移动,⿏标按键的按下和松开
键盘事件按键类型、按键按下、按键松开
定时器事件定时时间到达
进⼊离开事件⿏标的进⼊和离开
滚轮事件⿏标滚轮滚动
绘屏事件重绘屏幕的某些部分
显示隐藏事件窗⼝的显⽰和隐藏
移动事件窗⼝位置的变化
窗⼝事件是否为当前窗⼝
⼤⼩改变事件窗⼝⼤⼩改变
焦点事件键盘焦点移动
拖拽事件⽤⿏标进⾏拖拽

二、事件的处理

事件的处理一般常用做法是:重写相关的Event函数。

在 Qt 中,几乎所有的 Event 函数都是虚函数,所以可以重新实现。比如:在实现鼠标的进入和离开事件时,直接重新实现 enterEvent()leaveEvent() 即可。enterEvent() 和 leaveEvent() 函数原型如下:

(一)鼠标事件

1. 进入和离开事件

代码示例:使用enterEvent事件来实现,鼠标进入或者离开一个Label文本框,就在控制台输出对应的打印。

这里基类选择 QWidget,同时设置文本边界框,方便观察:

还需在项目中新设计一个类,然后让这个类继承于Label控件:

类创建好之后,给构造函数中添加一个父元素参数,方便Qt将我们创建的mylabel对象挂载到对象树上去。这个类已经继承了QLabel,重写两个事件函数就可以了:

#include "mylabel.h"
#include <QDebug>

mylabel::mylabel(QWidget *parent) : QLabel(parent) {}

void mylabel::enterEvent(QEvent *event)
{
    (void) event; // 这个参数暂时用不到
    qDebug() << "鼠标进入文本框";
}

void mylabel::leaveEvent(QEvent *event)
{
    (void) event; // 这个参数暂时用不到
    qDebug() << "鼠标离开文本框";
}

在ui界面选中文本框,右击点击 “提升为”,只有自己创建的mylabel才可以触发我们自己写的这个事件处理函数,一定要注意不要拼错类名:

之后这里的类名就变成了我们定义的mylabel了:

运行程序,鼠标每次进入或者离开文本框就会触发对应的处理函数,打印出对应的内容:

2. 鼠标点击事件

在Qt中,鼠标事件是用QMouseEvent类来实现的。当在窗口中按下鼠标或者移动鼠标时,都会产生鼠标事件。利用QMouseEvent类可以获取鼠标的哪个键被按下了以及鼠标的当前位置等信息。

在Qt帮助文档中查找QMouseEvent类,如下图示:

代码示例:当鼠标在Label文本框中点击时,则获取到鼠标坐标。

在Qt中,鼠标按下是通过虚函数mousePressEvent()来捕获的mousePressEvent()函数原型如下: 

  • Qt::LeftButton:鼠标左键
  • Qt::RightButton:鼠标右键
  • Qt::MidButton:鼠标滚轮

还有一点要注意的就是,不管是使用鼠标左键、右键还是滚轮,甚至按下侧键也可以触发这个事件:

#include <QMouseEvent>

void mylabel::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";
    else
        qDebug() << "其他键";

    // 以Label左上角为原点
    qDebug() << "以Label左上角为原点: " << event->x() << "," << event->y(); 
    // 以整个屏幕左上角为原点
    qDebug() << "以整个屏幕左上角为原点: " << event->globalX() << "," << event->globalY();
}

在文本框和内点击,就可以查看点击的坐标:

3. 释放事件

鼠标释放事件是通过mouseReleaseEvent()来捕获的:

void mylabel::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";
    else
        qDebug() << "其他键";
}

void mylabel::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
            qDebug() << "左键释放";
    else if (event->button() == Qt::RightButton)
        qDebug() << "右键释放";
    else
        qDebug() << "其他键释放";
}

4. 双击事件

双击事件通过虚函数mouseDoubleClickEvent()来实现:

void mylabel::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "双击左键";
    else if(event->button() == Qt::RightButton)
        qDebug() << "双击右键";
    else
        qDebug() << "双击其他键";
}

5. 移动事件

鼠标移动事件通过mouseMoveEvent()来实现,为了实时捕捉鼠标位置的信息,需要通过setMouseTracking()方法追踪鼠标的位置:

鼠标移动不同于以上操作。随便移动鼠标就会产生大量事件,当捕获这个事件时,再进行一些复杂的逻辑,那么程序负担就很重,很容易产生卡顿等问题。

所以 Qt 为了保证程序的流畅性,默认情况下不会对鼠标移动进行追踪,也就不会调用mouseMoveEvent,只有在构造函数中指明当前窗口需要捕捉鼠标移动事件,使用setMouseTracking()方法,参数设置为true:

mylabel::mylabel(QWidget *parent) : QLabel(parent)
{
    this->setMouseTracking(true);
}

void mylabel::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << event->x() << event->y();
}

6. 滚轮事件

Qt 中滚轮事件是通过QWheelEvent类实现的,而滚轮滑动的距离可以通过delta()方法获取:

void mylabel::wheelEvent(QWheelEvent *event)
{
    qDebug() << event->delta();
}

 打印的值为正负120,滚轮向上滚动为 +,向下滚动为 -

现在我们可以写一个通过滚轮调节字体大小的:

void mylabel::wheelEvent(QWheelEvent *event)
{
    QFont font = this->font();
    qDebug() << font;
    if (event->delta() > 0)
        font.setPointSize(font.pointSize() + 1);
    else if (event->delta() < 0)
        font.setPointSize(font.pointSize() - 1);
    this->setFont(font);
}

(二)键盘按键事件

Qt 中的按键事件是通过 QKeyEvent 类来实现的。当键盘上的按键被按下或者被释放时,键盘事件便会触发。

在帮助文档中查找 QKeyEvent 类如下:

1. 单个按键

之前我们也使用过QShortCut,这个是信号和槽封装的获取键盘的方式,站在更底层的角度课可以通过事件获取当前用户键盘按下的情况,使用的是keyPressEvent:

#include <QKeyEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    // qDebug() << event->key() << "按钮被按下"; // 打印ASCII值
    qDebug() << event->text() << "按钮被按下";
    if(event->key() == Qt::Key_A)
        qDebug() << "按下了a键";
}

运行效果如下: 

还有一点要注意的是,我们这里直接在QWidget中重写了这个事件函数,也可以在QMainWindow中重写这个事件函数,这里就要注意了,想要触发这个事件,一定要让该控件获取焦点,也就是说焦点不在,是触发不了事件的,什么是焦点,那就是要选中这个控件

2. 组合按键

Qt::KeyboardModifier 中定义了在处理键盘事件时对应的修改键。在 Qt 中,键盘事件可以与修改键⼀起使⽤,以实现⼀些复杂的交互操作。KeyboardModifier 中修改键的具体描述如下:

Qt::NoModifier⽆修改键
Qt::ShiftModifierShift 键
Qt::ControlModifierCtrl 键
Qt::AltModifierAlt 键
Qt::MetaModifierMeta键(在Windows上指Windows键,在macOS上指Command键)
Qt::KeypadModifier使⽤键盘上的数字键盘进⾏输⼊时,Num Lock键处于打开状态
Qt::GroupSwitchModifier⽤于在输⼊法 组之间 切换
void Widget::keyPressEvent(QKeyEvent *event)
{
    // 判断 a+ctrl 键是否被按下
    if(event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier)
        qDebug() << "ctrl+A 键被按下";
}

(三)定时器

Qt 在进行窗口程序处理的过程中,经常要周期性的执行某些操作,或者制作一些动画效果,使用定时器就可以实现,定时器就是间隔一段时间后执行某些任务。定时器在很多场景下都会使⽤到,如弹窗⾃动关闭之类的功能等。

Qt 中的定时器分为QTimerEventQTimer两个类:

  • QTimerEvent类:用来描述一个定时器事件,使用startTimer()函数来开启定时器,需要输入一个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表一个定时器。当定时器溢出时(定时时间到达)就可以在timeEvent()函数中获取该定时器的编号来进行相关操作。
  • QTimer类:用来实现定时器,它提供了更高一层的编程接口,比如:可以连接信号和槽,还可以设置只运行一次的定时器。QTimer 的背后是QTimerEvent 定时器事件进行支撑的。

1. QTimerEvent 

代码示例:在 UI 界面上放置一个 LCD Number 控件,让其 10 秒数字不断递减到 0,相当于倒计时。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 开启定时器事件
    // 返回一个定时器id
    timerId = this->startTimer(1000);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerEvent(QTimerEvent *event)
{
    // 如果一个程序中存在多个定时器(startTimer创建的定时器),此时每个定时器都会触发这个函数
    // 先判断
    if(event->timerId() != this->timerId) // 如果不是就忽略
        return;

    int value = ui->lcdNumber->intValue();
    if(value <= 0)
    {
        // 停止定时器
        this->killTimer(this->timerId);
        return;
    }
    value -= 1;
    ui->lcdNumber->display(value);
}

运行效果如下,倒计时:

使用timerEvnet比QTimer还要复杂,需要手动管理timerId,区分这次的timerId是否正确,所以后续还是使用QTimer。 

2. QTimer

代码示例:在UI界⾯放置⼀个 LCD 标签,两个按钮,分别是 “开始” 和 “停⽌” ,当点击 “开始” 按钮时,开始每隔1秒计数⼀次,点击 “停⽌” 按钮时,暂停计数。

#include <QTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QTimer *time = new QTimer(this);

    connect(ui->pushButton, &QPushButton::clicked, [=](){
        time->start(1000);
    });

    connect(time, &QTimer::timeout, [=](){
        static int num = 1;
        ui->label->setText(QString::number(num++));
    });

    connect(ui->pushButton_2, &QPushButton::clicked, [=](){
        time->stop();
    });
}

运行效果如下,按下开始按钮开始计时,停止按钮则停止:

(四)窗口事件

moveEvent窗口移动时触发的事件,resizeEvent 是窗口大小改变时触发的事件。

拖动窗口和调整窗口大小就会打印相应的内容。

#include <QMoveEvent>

void Widget::moveEvent(QMoveEvent *event)
{
    qDebug() << event->pos();
}

void Widget::resizeEvent(QResizeEvent *event)
{
    qDebug() << event->size();
}

三、事件分发器

在 Qt 中,事件分发器(Event Dispatcher) 是⼀个核⼼概念,⽤于处理 GUI 应⽤程序中的事件。事件分发器负责将事件从⼀个对象传递到另⼀个对象,直到事件被处理或被取消。每个继承⾃ QObject类 或QObject类 本⾝都可以在本类中重写 bool event(QEvent *e) 函数,来实现相关事件的捕获和拦截。

(一)事件分发器工作原理

在 Qt 中,我们发送的事件都是传给了 QObject 对象,更具体点是传给了 QObject 对象的 event() 函数所有的事件都会进⼊到这个函数⾥⾯,那么我们处理事件就要重写这个 event() 函数。event() 函数本⾝不会去处理事件,⽽是根据 事件类型(type值)调⽤不同的事件处理函数。事件分发器就是⼯作在应⽤程序向下分发事件的过程中,如下图:

如上图,事件分发器⽤于分发事件。在此过程中,事件分发器也可以做拦截操作。事件分发器主要是通过 bool event(QEvent *e) 函数来实现。其返回值为布尔类型,若为 ture,代表拦截,不向下分发。

上面是比较官方的理解,下面我来说一说自己对于Qt事件分发器的理解:
举个具体的例子:假设一个ui界面上有一个Label控件,现在我在这个Label控件上鼠标左键点击了一下,讲道理来说这是会触发这个Label控件的鼠标点击事件的,如果我们重写了mousePressEvent()事件,那么接下来Qt程序就会去调用这个事件处理函数,来处理用户做出点击操作,但是现在有了Qt事件分发器这一层,因此用户产生的这个点击事件,会先到事件分发器这一层,在这一层中用户可以来决定是否继续向下分发这个事件,如果用户在这一层拦截了这个鼠标点击事件,那么mousePressEvent()事件就不会被执行,转而去执行用户在事件分发层设计的一些拦截逻辑;相反,如果用户下放了这个事件,那么这个鼠标点击事件最终会被它的默认处理动作,也就是mousePressEvent()事件来进行处理。
        在这其中,每个控件的 bool event(QEvent* ev);接口被当作每个控件自己的事件分发器,对于一个控件来说,如果想要享受事件分发器的功能,那么就请重写event()接口,同时如果确实想要拦截的话,那么返回值请return true,否则return false。

代码示例:拦截一下鼠标左键点击事件

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMouseEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "鼠标左键被按下";
}

bool Widget::event(QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "Event中鼠标被按下";
        return true; // 返回true代表不向下分发
    }
    // 其他事件交给父类处理(默认处理)
    return QWidget::event(event);
}

 运行效果如下,当在窗口中点击鼠标左键时,就会执行event函数,而不会执行mousePressEvent函数:

四、事件过滤器

在 Qt 中,一个对象可能经常要查看或拦截另外一个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等。通过上面的学习,我们已经知道,Qt 创建了 QEvent 事件对象之后,会调用 QObject 的 event() 函数 处理事件的分发。显然,我们可以在 event() 函数中实现拦截的操作。由于 event() 函数是 protected 的,因此,需要继承已有类。如果组件很多,就需要重写很多个 event() 函数。这当然相当⿇烦,更不用说重写 event() 函数还得小心一堆问题。好在 Qt 提供了另外一种机制来达到这一目的:事件过滤器。

事件过滤器是在应用程序分发到 event 事件分发器 之前,再做一次更高级的拦截。

上面是对于事件过滤器比较官方的解释,我来说一说我自己对于事件过滤器的理解:
诚然,上面我们了解到的事件分发器似乎也能做到过滤的作用,但是事件分发器的过滤只能针对于一个控件本身所发出的事件进行过滤,如果有多个不同的控件,都有事件需要进行过滤操作,那么每个控件就都得重写自己的事件分发器(bool event(QEvent*ev);) ,这显然是费时费力的方式,因此为了高效的完成事件过滤工作,Qt提出了事件过滤器的概念。

事件过滤器的一般使用步骤:

  1. 创建事件过滤器

    要实现事件过滤器,需要创建一个继承于QObject的类,并重写里面的eventFilter()函数;该函数会在事件到达控件对象时被调用,开发者可以在其中处理事件并返回布尔值来指示是否拦截该事件。如果返回true,表示事件已被拦截,如果返回false,则表示事件尚未被处理,继续向下传递;
     
  2. 安装事件过滤器

    使用QObject类中的installEventFilter()函数将事件过滤器安装到目标对象上。安装事件过滤器的对象可以是任何继承自QObject的类,包括窗口、控件等。安装完成后,当目标对象接收到事件时,事件过滤器就会被调用。
     
  3. 事件处理与分发

    eventFilter()函数内部,你可以对事件进行预处理,然后根据需要调用QEvent::accept()来接受事件,或QEvent::ignore()来忽略事件。如果事件不被过滤器处理,它应该返回false以允许事件继续传递给其原始的接收者。

代码示例:演示事件过滤器的使用

在ui界面上设计一个Label,并带有边框,并提升:

重写一个Label类,让其继承自QLabel,并将其命名为mylabel,并在mylabel.cpp" 文件中实现鼠标点击事件和事件分发器:

#include "mylabel.h"
#include <QMouseEvent>
#include <QDebug>

mylabel::mylabel(QWidget *parent) : QLabel(parent)
{

}

void mylabel::mousePressEvent(QMouseEvent *event)
{
    QString str = QString("鼠标按下: x = %1, y = %2").arg(event->x()).arg(event->y());
    qDebug() << str.toUtf8().data();
}

bool mylabel::event(QEvent *event)
{
    // 如果是鼠标按下,在event事件分发时做拦截操作
    if(event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *event = static_cast<QMouseEvent *>(event);
        QString str = QString("Event函数中鼠标按下: x = %1, y = %2").arg(event->x()).arg(event->y());
        qDebug() << str.toUtf8().data();

        return true;
    }
    // 其他事件交给父类处理
    return QLabel::event(event);
}

在 "widget.cpp" 文件中实现事件过滤器:

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMouseEvent>
#include <QEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. label安装事件过滤器 this:当前窗口安装事件过滤器
    ui->label->installEventFilter(this);
}

Widget::~Widget()
{
    delete ui;
}

// 2. 重写
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if(obj == ui->label) // 判断控件
    {
        if(event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *event = static_cast<QMouseEvent *>(event);
            QString str = QString("事件过滤器中鼠标按下: x = %1, y = %2").arg(event->x()).arg(event->y());
            qDebug() << str.toUtf8().data();

            return true;
        }
    }
    // 其他的交给父类处理
    return QWidget::eventFilter(obj, event);
}

运行效果如下,在标签中点击鼠标不会执行event函数,而是执行eventFilter函数

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

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

相关文章

如何判断监控设备是否支持语音对讲

目录 一、大华摄像机 二、海康摄像机 三、宇视摄像机 一、大华摄像机 注意&#xff1a;大华摄像机支持跨网语音对讲&#xff0c;即设备和服务器可以不在同一网络内&#xff0c;大华设备的语音通道填写&#xff1a;34020000001370000001 配置接入示例&#xff1a; 音频输入…

十日Python项目——第七日(商品购物车)

#前言&#xff1a; 在最近十天我会用Python做一个购物类电商项目&#xff0c;会用到DjangoMysqlRedisVue等。 今天是第六天&#xff0c;主要负责撰写编写关于商品购物车的编写&#xff0c;以及相应的增删改查。若是有不懂大家可以先阅读我的前六篇博客以能够顺承。 若是大家…

Github Copilot 使用技巧

&#x1f3af;目标读者 本文不包含如何安装 Github Copilot本文介绍了 Github Copilot 使用方法和一些技巧 本人已经使用 Github Copilot 2 年了&#xff0c;交了 3 次年费&#xff0c;每年 100$ 着实心痛&#xff0c;但是用着确实爽歪歪 但是感觉一直只用了一小部分功能&am…

(第二十七天)

上午 核心&#xff1a;内核中的 ipvs &#xff0c; ipvsadm 1 、安装 ipvsadm [rootnat ~] # yum -y install ipvsadm 2 、配置规则 查看所有的规则&#xff0c;如果已经配置好规则&#xff0c;重启之后也就没有了 [rootnat ~] # ipvsadm -L -n 1 、配置 vip 网卡 &…

服装租赁押金管理-押金原路退回系统开通方法

一、婚纱影楼服装租赁收押金必要性 1. 保障服装的按时归还&#xff1a; - 押金的存在能促使租客按时归还服装&#xff0c;避免因拖延归还影响后续的租赁业务。比如&#xff0c;在一些大型活动期间&#xff0c;服装租赁需求旺盛&#xff0c;如果租客不按时归还&#xff0c;…

HTML样式- CSS——WEB开发系列08

一、HTML 基础概述 HTML 用于创建网页的结构。网页的所有内容&#xff0c;例如文本、图像、链接、表单等&#xff0c;都是通过 HTML 标签来定义的。以下是一个简单的 HTML 文档结构示例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><…

matlab 音频音量处理(音量大小按照dB调节)

1 音量(声压级)以分贝(dB)表示的计算公式为: 2 % 已知的 x 值 x = 0:-1:-127; % 在这里填入 x 的具体值% 计算 y %y = 10

浅谈php://filter的妙用

文章目录 分析源码巧用编码与解码利用字符串操作方法 分析源码 <?php $content <?php exit; ?>; $content . $_POST[txt]; file_put_contents($_POST[filename], $content);首先&#xff0c;先分析一下这段代码。 首先他定义了content为’<?php exit;?>‘…

计算机网络17——IM聊天系统——客户端核心处理类框架搭建

目的 拆开客户端和服务端&#xff0c;使用Qt实现客户端&#xff0c;VS实现服务端 Qt创建项目 Qt文件类型 .pro文件&#xff1a;配置文件&#xff0c;决定了哪些文件参与编译&#xff0c;怎样参与编译 .h .cpp .ui&#xff1a;画图文件 Qt编码方式 Qt使用utf-8作为编码方…

服务器被ddos攻击多久能恢复?具体怎么操作

服务器被ddos攻击多久能恢复&#xff1f;如果防御措施得当&#xff0c;可能几分钟至几小时内就能缓解&#xff1b;若未采取预防措施或攻击特别猛烈&#xff0c;则可能需要几小时甚至几天才能完全恢复。服务器被DDoS攻击的恢复时间取决于攻击的规模和强度、服务器的配置和性能以…

【C++】类与对象(中)_7.const成员函数

7.const成员 7.1 const修饰类的成员函数 将const修饰的类成员函数称之为const成员函数&#xff0c;const修饰类成员函数&#xff0c;实际修饰该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进行修改。 我们来看看下面的代码 #define _CRT_SECU…

【ARM CoreLink 系列 5.1 -- CI-700 各种 Node 组件详细介绍】

请阅读【ARM CoreLink 文章专栏导读】 文章目录 CI-700 组件(Components)RN-I( I/O-coherent Request Node) 和 RN-D(I/O coherent Request Node with DVM)HN-F(Fully coherent Home Node)IO coherent Home Node (HN-I)IO coherent Home Node with Debug Trace Controller (H…

JSON与Jsoncpp库:数据交换的灵活选择

目录 引言 一.JSON简介 二. Jsoncpp库概述 三. Jsoncpp核心类介绍 3.1 Json::Value类 3.2 序列化与反序列化类 四. 实现序列化 五. 实现反序列化 结语 引言 在现代软件开发中&#xff0c;数据交换格式扮演着至关重要的角色。JSON&#xff08;JavaScript Object Notati…

鸿蒙(API 12 Beta3版)【媒体会话提供方】本地媒体会话

音视频应用在实现音视频功能的同时&#xff0c;需要作为媒体会话提供方接入媒体会话&#xff0c;在媒体会话控制方&#xff08;例如播控中心&#xff09;中展示媒体相关信息&#xff0c;及响应媒体会话控制方下发的播控命令。 基本概念 媒体会话元数据&#xff08;AVMetadata…

WordPress原创插件:Download-block-plugin下载按钮图标美化

WordPress原创插件&#xff1a;Download-block-plugin下载按钮图标美化 https://download.csdn.net/download/huayula/89632743

Mapreduce_csv_averageCSV文件计算平均值

csv文件求某个平均数据 查询每个部门的平均工资&#xff0c;最后输出 数据处理过程 employee_noheader.csv&#xff08;没做关于首行的处理&#xff0c;运行时请自行删除&#xff09; EmployeeID,EmployeeName,DepartmentID,Salary 1,ZhangSan,101,5000 2,LiSi,102,6000…

疫情下图书馆管理系统

TOC springboot126疫情下图书馆管理系统 系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管…

mock.js的简单使用~

1、什么是mock? mock.js:是一款模拟数据生成器&#xff0c;可以生成随机数据&#xff0c;拦截 Ajax 请求. 2、mock的作用。 可以通过mock来模拟后端接口&#xff0c;可随机生成所需数据&#xff0c;模拟对数据的增删改查。并且截Ajax请求不需要修改既有代码就可以拦截&…

RCE-eval长度限制突破技巧

目录 一、长度17的限制绕过 1、最简单的绕过 &#xff08;一&#xff09;绕过 &#xff08;二&#xff09;编写一句话木马 2、文件包含的利用 &#xff08;一&#xff09;远程文件包含的利用 &#xff08;二&#xff09;本地文件包含的利用 3、usort绕过 &#xff08…

BGP路由优选(五)

当到达同一个目的网段存在多条路由时&#xff0c;BGP通过如下的次序进行路由优选&#xff1a; 丢弃下一跳不可达的路由。 优选Preferred-Value属性值最大的路由。优选Local_Preference属性值最大的路由。本地始发的BGP路由优于从其他对等体学习到的路由&#xff0c;本地始发的路…