[Qt]事件

news2024/9/23 11:20:58

文章摘于 爱编程的大丙

文章目录

  • 1. 事件处理器
    • 1.1 事件
    • 1.2 事件处理器函数
      • 1.2.1 鼠标事件
      • 1.2.2 键盘事件
      • 1.2.3 窗口重绘事件
      • 1.2.4 窗口关闭事件
      • 1.2.5 重置窗口大小事件
    • 1.3 重写事件处理器函数
      • 1.3.1 头文件
      • 1.3.2 源文件
      • 1.3.3 效果
    • 1.4 自定义按钮
      • 1.4.1 添加子类
      • 1.4.2 使用自定控件
      • 1.4.3 设置图片
  • 2. 事件分发器
    • 2.1 QEvent
    • 2.2 事件分发器
  • 3. 事件过滤器
    • 3.1 事件过滤器
    • 3.2 事件过滤器的使用


1. 事件处理器

1.1 事件

Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。
所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过:事件派发 -> 事件过滤->事件分发->事件处理几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作。

事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。

每一个Qt应用程序都对应一个唯一的 QApplication应用程序对象,然后调用这个对象的exec()函数,这样Qt框架内部的事件检测就开始了(程序将进入事件循环来监听应用程序的事件)。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow* w = new MainWindow;
    w.show();
    return a.exec();
}

事件在Qt中产生之后,的分发过程是这样的:

  1. 当事件产生之后,Qt使用用应用程序对象调用notify()函数将事件发送到指定的窗口:
[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);
  1. 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
// 需要先给窗口安装过滤器, 该事件才会触发
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
  1. 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:
[override virtual protected] bool QWidget::event(QEvent *event);
  1. 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函数),比如:鼠标事件:
// 鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
// 鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
// 鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);

1.2 事件处理器函数

通过上面的描述可以得知:Qt的事件处理器函数处于食物链的最末端,每个事件处理器函数都对应一个唯一的事件,这为我们重新定义事件的处理动作提供了便利。
另外,Qt提供的这些事件处理器函数都是回调函数,也就是说作为使用者我们只需要指定函数的处理动作,关于函数的调用是不需要操心的,当某个事件被触发,Qt框架会调用对应的事件处理器函数。

QWidget类是Qt中所有窗口类的基类,在这个类里边定义了很多事件处理器函数,它们都是受保护的虚函数。我们可以在Qt的任意一个窗口类中重写这些虚函数来重定义它们的行为。下面介绍一些常用的事件处理器函数:

1.2.1 鼠标事件

  • 鼠标按下事件
    当鼠标左键、鼠标右键、鼠标中键被按下,该函数被自动调用,通过参数可以得到当前按下的是哪个鼠标键
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
  • 鼠标释放事件
    当鼠标左键、鼠标右键、鼠标中键被释放,该函数被自动调用,通过参数可以得到当前释放的是哪个鼠标键
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
  • 鼠标移动事件
    当鼠标移动(也可以按住一个或多个鼠标键移动),该函数被自动调用,通过参数可以得到在移动过程中哪些鼠标键被按下了。
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);
  • 鼠标双击事件
    当鼠标双击该函数被调用,通过参数可以得到是通过哪个鼠标键进行了双击操作。
[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event);
  • 鼠标进入事件
    当鼠标进入窗口的一瞬间,触发该事件,注意:只在进入的瞬间触发一次该事件
[virtual protected] void QWidget::enterEvent(QEvent *event);
  • 鼠标离开事件
    当鼠标离开窗口的一瞬间,触发该事件,注意:只在离开的瞬间触发一次该事件
[virtual protected] void QWidget::leaveEvent(QEvent *event);

1.2.2 键盘事件

  • 键盘按下事件
    当键盘上的按键被按下了,该函数被自动调用,通过参数可以得知按下的是哪个键。
[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event);
  • 键盘释放事件
    当键盘上的按键被释放了,该函数被自动调用,通过参数可以得知释放的是哪个键。
[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event);

1.2.3 窗口重绘事件

当窗口需要刷新的时候,该函数就会自动被调用。窗口需要刷新的情景很多,比如:窗口大小发生变化,窗口显示等,另外我们还可以通过该函数给窗口绘制背景图,总之这是一个需要经常被重写的一个事件处理器函数。

[virtual protected] void QWidget::paintEvent(QPaintEvent *event);

1.2.4 窗口关闭事件

当窗口标题栏的关闭按钮被按下并且在窗口关闭之前该函数被调用,可以通过该函数控制窗口是否被关闭。

[virtual protected] void QWidget::closeEvent(QCloseEvent *event);

1.2.5 重置窗口大小事件

当窗口的大小发生变化,该函数被调用。

[virtual protected] void QWidget::resizeEvent(QResizeEvent *event);

除此之外,关于Qt窗口提供的其他事件处理器函数还有很多,感兴趣的话可以仔细阅读Qt的帮助文档,窗口的事件处理器函数非常好找,规律是这样的:

  1. 受保护的虚函数
  2. 函数名分为两部分: 事件描述+Event
  3. 函数带一个事件类型的参数

1.3 重写事件处理器函数

由于事件处理器函数都是虚函数,因此我们就可以添加一个标准窗口类的派生类,这样不仅使子类继承了父类的属性,还可以在这个子类中重写父类的虚函数,总起来说整个操作过程还easy

  1. 创建一个Qt项目,添加一个窗口类(让其从某个标准窗口类派生)
  2. 在子类中重写从父类继承的虚函数(也就是事件处理器函数)

1.3.1 头文件

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    // 重写事件处理器函数
    void closeEvent(QCloseEvent* ev);
    void resizeEvent(QResizeEvent* ev);

private:
    Ui::MainWindow *ui;
};

1.3.2 源文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCloseEvent>
#include <QMessageBox>
#include <QResizeEvent>
#include <QDebug>

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

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

void MainWindow::closeEvent(QCloseEvent *ev)
{
    QMessageBox::Button btn = QMessageBox::question(this, "关闭窗口", "您确定要关闭窗口吗?");
    if(btn == QMessageBox::Yes)
    {
        // 接收并处理这个事件
        ev->accept();
    }
    else
    {
        // 忽略这个事件
        ev->ignore();
    }
}

void MainWindow::resizeEvent(QResizeEvent *ev)
{
    qDebug() << "oldSize: " << ev->oldSize()
             << "currentSize: " << ev->size();
}

QCloseEvent类是QEvent类的子类,程序中使用的accept()或者ignore()的作用参考时间分发器部分的QEvent


1.3.3 效果

在上面重写的closeEvent事件中添加了关闭窗口的判断,这样就可以避免误操作导致窗口被关闭了,效果如下:
在这里插入图片描述

如果想要时时检测窗口大小,就可以重写窗口的resizeEvent事件,这样就可以得到窗口的最新尺寸信息了:
在这里插入图片描述


1.4 自定义按钮

基于Qt提供的事件处理器函数,我们可以非常轻松地按照自己的想法制作出一个按钮,按钮的要求如下:

  1. 从视觉上看是一个不规则按钮(按钮实际上都是矩形的)
  2. 按钮上需要显示指定的背景图片
  3. 按钮在鼠标的不同操作阶段(无操作、鼠标悬停、鼠标按下)能够显示不同的背景图

1.4.1 添加子类

新添加的按钮类可以让它继承 QPushButton,也可以让它继承其他的窗口类(代价是当鼠标点击事件触发之后需要自己发射自定义信号),这里让添加的子类从QWidget类派生。

自定义类头文件

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);

    void setImage(QString normal, QString hover, QString pressed);

protected:
    void mousePressEvent(QMouseEvent* ev);
    void mouseReleaseEvent(QMouseEvent* ev);
    void enterEvent(QEvent* ev);
    void leaveEvent(QEvent* ev);
    void paintEvent(QPaintEvent* ev);

signals:
    void clicked();

private:
    QPixmap m_normal;
    QPixmap m_press;
    QPixmap m_hover;
    QPixmap m_current;
};

#endif // MYBUTTON_H

自定义类源文件

#include "mybutton.h"

#include <QPainter>

MyButton::MyButton(QWidget *parent) : QWidget(parent)
{

}

void MyButton::setImage(QString normal, QString hover, QString pressed)
{
    // 加载图片
    m_normal.load(normal);
    m_hover.load(hover);
    m_press.load(pressed);
    m_current = m_normal;
    // 设置按钮和图片大小一致
    setFixedSize(m_normal.size());
}

void MyButton::mousePressEvent(QMouseEvent *ev)
{
    // 鼠标被按下, 发射这个自定义信号
    emit clicked();
    m_current = m_press;
    update();
}

void MyButton::mouseReleaseEvent(QMouseEvent *ev)
{
    m_current = m_normal;
    update();
}

void MyButton::enterEvent(QEvent *ev)
{
    m_current = m_hover;
    update();
}

void MyButton::leaveEvent(QEvent *ev)
{
    m_current = m_normal;
    update();
}

void MyButton::paintEvent(QPaintEvent *ev)
{
    QPainter p(this);
    p.drawPixmap(rect(), m_current);
}

1.4.2 使用自定控件

由于Qt的UI工具箱中提供的都是标准控件,自定义的控件是不能直接拖拽到UI窗口中的,这时我们需要先看一下自定义控件的基类类型:上面自定义的 MyButton 的基类是 QWidget 类型,因此需要往窗口中拖拽一个QWidget类型的标准控件,然后在这个标准控件上鼠标右键:

在这里插入图片描述

这样添加的控件类型就变成了自定义的子类类型:
在这里插入图片描述


1.4.3 设置图片

在主窗口中通过添加的按钮的对象,调用子类的成员函数给其添加图片:

mainwindow.cpp

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

    // 给自定义按钮设置图片
    ui->button->setImage(":/ghost-1.png", ":/ghost-2.png", ":/ghost-3.png");
    // 处理自定义按钮的鼠标点击事件
    connect(ui->button, &MyButton::clicked, this, [=]()
    {
        QMessageBox::information(this, "按钮", "莫要调戏我...");
    });
}

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

2. 事件分发器

2.1 QEvent

当事件产生被发送到对应的窗口之后,窗口并不会直接处理这个事件,而是对这些事件进行细分,然后根据事件的类型再次进行分发(相当于公司接了个项目,对项目进行查分之后分发给各个职能部门,由各个部门进行模块的开发),对应的事件处理器函数得到这个分发的事件之后就开始处理这个事件。

关于窗口事件的分发,对应一个事件分发器,叫做event

[override virtual protected] bool QWidget::event(QEvent *event);

通过事件分发器的函数原型可以得知,关于事件类型的判断是基于参数完成的,这个参数是一个QEvent类型的对象,下面来看一下这个类中常用的一些API函数:

void QEvent::accept();
  • 该函数的作用是让窗口接受传递过来的事件,事件不会向上层窗口(父窗口)传递。
void QEvent::ignore();
  • 该函数的作用是让窗口忽略传递过来的事件,事件被传递给父窗口(向上传递)。
bool QEvent::isAccepted() const;
void QEvent::setAccepted(bool accepted);
  • 设置传递过来的事件是被接受还是被忽略
    • setAccepted(true) == accept()
    • setAccepted(false) == ignore()
QEvent::Type QEvent::type() const;
  • 得到传递的窗口的事件的类型,返回值是一个枚举类型,内容很多可以自己查帮助文档

在这里插入图片描述


2.2 事件分发器

在不需要人为干预的情况下,事件分发器会自主的完成相关事件的分发,下面来还原一下事件分发器的分发流程,以下是这个函数的部分源码展示:

bool QWidget::event(QEvent *ev)
{
    switch(ev->type())
    {
    // 鼠标移动
    case QEvent::MouseMove:		
        mouseMoveEvent((QMouseEvent*)event);
        break;
    // 鼠标按下
    case QEvent::MouseButtonPress:	
        mousePressEvent((QMouseEvent*)event);
        break;
    // 鼠标释放
    case QEvent::MouseButtonRelease:	
        mouseReleaseEvent((QMouseEvent*)event);
        break;
    // 鼠标双击
    case QEvent::MouseButtonDblClick:	
        mouseDoubleClickEvent((QMouseEvent*)event);
        break;
    // 键盘按键被按下事件
    case QEvent::KeyPress:
        break;
        ...
        ...
        ...
    default:
        break;
    }
}

可以直观的看到事件分发器在对事件进行判定之后会调用相关的事件处理器函数,这样事件就被最终处理掉了。

如果我们不想让某些触发的事件进入到当前窗口中,可以在事件分发器中进行拦截,拦截之前先来了解一下事件分发器函数的返回值:

  1. 如果传入的事件已被识别并且处理,则需要返回 true,否则返回 false。如果返回值是 true,那么 Qt 会认为这个事件已经处理完毕,不会再将这个事件发送给其它对象,而是会继续处理事件队列中的下一事件。

  2. 在event()函数中,调用事件对象的 accept() 和 ignore() 函数是没有作用的,不会影响到事件的传播。

也就是说如果想过滤某个事件,只需要在判断出这个事件之后直接返回 true 就可以了。

下面来举个例子,在窗口中过滤掉鼠标按下的事件:

bool MainWindow::event(QEvent *ev)
{
    if(ev->type() == QEvent::MouseButtonPress ||
            ev->type() == QEvent::MouseButtonDblClick)
    {
        // 过滤调用鼠标按下的事件
        return true;
    }
    return QWidget::event(ev);
}

这样窗口就再也收不到鼠标的单击和双击事件了,对于这两个事件以外的其他事件是没有任何影响的,因为在重写的事件分发器函数的最后调用了父类的事件分发器函数

return QWidget::event(ev);

这样就能保证其他事件按照默认的分发流程进行分发,并最终被窗口处理掉。


3. 事件过滤器

3.1 事件过滤器

除了使用事件分发器来过滤Qt窗口中产生的事件,还可以通过事件过滤器过滤相关的事件。当Qt的事件通过应用程序对象发送给相关窗口之后,窗口接收到数据之前这个期间可对事件进行过滤,过滤掉的事件就不能被继续处理了。QObject有一个eventFilter()函数,用于建立事件过滤器。函数原型如下:

[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event);
  • 参数:
    • watched:要过滤的事件的所有者对象
    • event:要过滤的具体的事件
  • 返回值:如果想过滤掉这个事件,停止它被进一步处理,返回true,否则返回 false

既然要过滤传递中的事件,首当其冲还是要搞明白如何通过事件过滤器进行事件的过滤,主要分为两步:

  1. 给要被过滤事件的类对象安装事件过滤器
void QObject::installEventFilter(QObject *filterObj);

假设调用installEventFilter()函数的对象为当前对象,那么就可以基于参数指定的filterObj对象来过滤当前对象中的指定的事件了。

  1. 在要进行事件过滤的类中(filterObj 参数对应的类)重写从QObject类继承的虚函数eventFilter()。

3.2 事件过滤器的使用

根据上面的使用步骤,举一个例子:

在一个窗口中有一个多行文本输入框QTextEdit,需要让我们屏蔽掉键盘上的回车键,也就是按回车键之后在这个文本编辑框中再也不能换行了。

其实上面的需求有三种解决方案:

  1. 自定义一个新的类让其继承QTextEdit,在这个子类中重写键盘事件keyPressEvent,在这个函数里边屏蔽掉回车键
  2. 自定义一个新的类让其继承QTextEdit,在这个子类中重写事件分发器event,在这个函数里边屏蔽掉回车键
  3. QTextEdit安装事件过滤器,基于QTextEdit的父窗口对这个控件的事件进行过滤

最简单的方式还是第三种,因为我们不需要再定义出一个子类就可以轻松的完成控件事件的过滤了。

准备工作:在主窗口中添加一个QTextEdit类型的控件,如下图:
在这里插入图片描述

主窗口头文件: mainwindow.h

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    bool eventFilter(QObject *watched, QEvent *event);


private:
    Ui::MainWindow *ui;
};

主窗口源文件: mainwindow.cpp

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

    ui->textEdit->installEventFilter(this);
}

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

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    // 判断对象和事件
    if(watched == ui->textEdit && event->type() == QEvent::KeyPress)
    {
        QKeyEvent* keyEv = (QKeyEvent*)event;
        if(keyEv->key() == Qt::Key_Enter ||         // 小键盘确认
                keyEv->key() == Qt::Key_Return)     // 大键盘回车
        {
            qDebug() << "我是回车, 被按下了...";
            return true;
        }
    }
    return false;
}

在示例代码的第7行:给多行编辑框控件安装了事件过滤器,由this对应的主窗口进行事件的过滤

在示例代码的第15行:主窗口通过重新事件过滤器函数,对多行编辑框控件进行事件的过滤,在函数体内部关于键盘事件的过滤需要判断按键是否是回车键,此处需要注意:

  • Qt::Key_Enter是小键盘上的回车(确认)键,有些键盘没有小键盘,因此也就没有该按键。
  • Qt::Key_Return是大键盘上的回车键

通过这样的处理,事件在被应用程序对象发送出去之后,进入到对应的窗口之前就被其父窗口过滤掉了。

如果在Qt的窗口中有多层嵌套的窗口,如下图:
在这里插入图片描述

先来描述一下这四层窗口的关系:

  • 顶层窗口A的直接子窗口是 B,间接子窗口是 C,QTextEdit
  • 二级窗口B的直接子窗口是 C,间接子窗口是 QTextEdit
  • 三级窗口C的直接子窗口是 QTextEdit

在这种多层嵌套窗口中如果想要过滤掉QTextEdit的某些事件,可以交给A或者B或者C去处理,当然也可以给QTextEdit同时安装多个过滤器:

ui->textEdit->installEventFilter(窗口A对象);
ui->textEdit->installEventFilter(窗口B对象);
ui->textEdit->installEventFilter(窗口C对象);

如果一个对象存在多个事件过滤器,那么,最后一个安装的会第一个执行,也就是说窗口C先进行事件过滤,然后窗口B,最后窗口A。

注意:
事件过滤器和被安装过滤器的组件必须在同一线程,否则,过滤器将不起作用。另外,如果在安装过滤器之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候过滤器才会有效。


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

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

相关文章

ECS-7000S集中空调节能控制和管理系统 制冷机房集群控制系统解决方案

ECS-7000S集中空调节能控制和管理系统 自动调整冷水主机运行台数 ECS-7000S制冷机房集群控制系统 公司是一家从事智能电网用户端的智能电力监控与电气安全系统的研发,生产和销售于一体的高新技术企业&#xff0c;自主研发了风机节能控制器,新风空调节能控制器,电梯节能控制器…

报团取暖!

大家好&#xff0c;我是技术UP主小傅哥。 3600人的加入&#xff0c;600多天的运营&#xff0c;其实小傅哥还悄悄的运营了一个免费的帮助大家找工作的星球&#xff0c;现在已经有非常多的伙伴加入&#xff0c;并分享许多公司的实习、校招、内推岗位&#xff0c;也有很多伙伴在线…

Python实战 | 如何使用 Python 调用 API

**本文目录 ** 一、前言 二、调用浙江数据开放平台API获取数据 &#xff08;一&#xff09;API获取数据的流程 &#xff08;二&#xff09;HTTP请求 &#xff08;三&#xff09;API的参数 &#xff08;四&#xff09;使用request库获取API数据 三、调用百度通用翻译API **四、*…

管理方法论:6. 正视团队冲突——化解危机,长治久安

概念 团队冲突指的是两个或两个以上的团队在目标、利益、认识等方面互不相容或互相排斥&#xff0c;从而产生心理或行为上的矛盾&#xff0c;导致抵触、争执或攻击事件。 参考&#xff1a; https://baike.baidu.com/item/%E5%9B%A2%E9%98%9F%E5%86%B2%E7%AA%81/6747073 htt…

PAL/NTSC/1080I和interlaced scan(隔行扫描)

目录 1.PAL/NTSC和1080I 2.PAL/NTSC/1080I的timing 2.1 NTSC的垂直同步 2.2 PAL的垂直同步​编辑 2.3 1080i50FPS的vic20的时序 3.interlaced video timing实现说明 1.PAL/NTSC和1080I NTSC 和PAL 是两种不同视讯标准, 两种都是CRT时代遗留下的产物, 也都使用Interlace技术…

深度学习-卷积神经网络-卷积图像去噪边缘提取-图像去噪 [北邮鲁鹏]

目录标题 参考学习链接图像噪声噪声分类椒盐噪声脉冲噪声对椒盐噪声&脉冲噪声去噪使用高斯卷积核中值滤波器 高斯噪声减少高斯噪声 参考学习链接 计算机视觉与深度学习-04-图像去噪&卷积-北邮鲁鹏老师课程笔记 图像噪声 噪声点&#xff0c;其实在视觉上看上去让人感…

JAVA面向对象(OOP)总结----宏观的程序设计

类&#xff1a;使用关键字class&#xff0c;抽象的概念集合。例如人类&#xff0c;具有共性的产物。 对象&#xff1a;具有自己独立属性&#xff0c;具有个性的个体。 类中可以定义的内容&#xff1a; 成员变量&#xff08;属性&#xff09;&#xff1b;成员方法&#xff08;…

内网穿透:实现远程访问和测试内部网络的关键技术

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 内网穿透是一项重…

基于ssm的蛋糕预定网站

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

BLCD无刷电机三相电流采样说明与总结

最近在在搞无刷电机电流采集&#xff0c;查了跟多资料&#xff0c;做个小记录&#xff0c;只记录低端和高端的三电阻采集&#xff0c;因为双电阻和但电阻比较麻烦&#xff0c;脑子不够用。 一、高端电流采样 高端采样&#xff1a;如上图&#xff08;红色波形&#xff09;&…

Allure的下载和部署

介绍 Allure是一个功能强大的测试报告和测试管理框架&#xff0c;旨在提供清晰、易于理解的测试结果。它支持多种编程语言和测试框架&#xff0c;并提供了丰富的图形化报告&#xff0c;包括图表、图像和日志&#xff0c;以帮助团队更好地分析和诊断测试问题。 下载 这里提供…

老站长带你全面认识基站和天线

认识基站 作为数量最多的移动通信设备 基站几乎是随处可见 其实 基站也分为很多种 基站的天线&#xff0c;也分为很多种&#xff0c;真正都能区分清楚的人其实不多。 什么是基站 Base Station 一般特指“公用移动通信基站” 大家都知道&#xff0c;基站就是给手机提供信…

uni-app 实现自定义按 A~Z 排序的通讯录(字母索引导航)

创建 convertPinyin.js 文件 convertPinyin.js 将下面的内容复制粘贴到其中 const pinyin (function() {let Pinyin function(ops) {this.initialize(ops);},options {checkPolyphone: false,charcase: "default"};Pinyin.fn Pinyin.prototype {init: functi…

在IntelliJ IDEA 中安装阿里P3C以及使用指南

在IntelliJ IDEA 中安装阿里P3C以及使用指南 1.关于阿里p3c1.1说明1.2什么是P3C插件1.3p3c的作用是什么 2 如何在IDEA中安装p3c2.1 插件安装2.2 插件使用 1.关于阿里p3c 1.1说明 代码规范检查插件P3C&#xff0c;是根据《阿里巴巴java开发手册(黄山版)》转化而成的自动化插件…

pdf转cad怎么弄?教你这几种快速转换cad的方法

pdf转cad怎么弄&#xff1f;随着CAD软件的广泛应用&#xff0c;将PDF文件转换为CAD文件的需求也越来越大。虽然市面上有很多PDF转CAD的软件&#xff0c;但是很多软件操作复杂&#xff0c;转换效果并不理想。今天就给大家推荐几种简单方便的转换方法。 方法一&#xff1a;迅捷PD…

arm day2(9.15)数据操作指令,跳转指令,特殊功能寄存器指令,

作业 1.求最大公约数&#xff1a; .text .global _start _start:mov r0,#0x9mov r1,#0x15bl Loop Loop:cmp r0,r1 比较r0寄存器和r1寄存器的中的值beq stop 当两数相同时,退出程序subhi r0,r0,r1 r0>r1 r0 r0 - r1subcc r1,r1,r0 r0<r1 r1 r1 - r0mov pc,lr 恢复现…

Year 2038 problem

前情回顾 已经知道,对于int了tinyint了这些MySql类型,后面那个4或者11没啥实际意义,只是说(当位数不足时)前面填充多少个0,然后使之变为4位或者11位,对这个类型的字段实际能存的长度没啥影响. 即占据1个Byte的tinyint类型,最多就能表征256个不同值. 可以表征无符号的连续数字0-…

在工作流引擎设计领域,是否自动计算未来的处理人的设计模式有哪些?

概述 流程的第一个节点发送下去的时候&#xff0c;就要把以后所有节点的处理人计算出来,能清楚的知道每个节点都是那些人处理. 以驰骋bpm为例来说明这个设计 计算未来处理人包括抄送节点、与待办节点. 默认的模式为&#xff1a;每个节点发送的时候即使计算,就是不计算未来处理…

Linux 软件包管理器-yum使用

文章目录 前言一、yum使用1、什么是软件包2、yum源3、yum list 指令4、yum install 指令5、yum remove指令 二、git的使用1、gitee中仓库的创建2、仓库的克隆3、提交代码到远程仓库4、提交时可能遇到的问题5、.gitignore文件6、删除文件 前言 一、yum使用 1、什么是软件包 在…

发过的朋友圈怎么再快速发一次?

发过的朋友圈怎么再快速发一次&#xff1f; 大部分人第一反应都是去朋友圈 直接翻找&#xff0c;然后保存图片、文案 再重新编辑一次发布朋友圈 有没有快速一点的方法呢&#xff1f; 当然有啦&#xff01; 推荐这款工具 就可以直接把发过的朋友圈再发一次 重发朋友圈 一键…