视频链接
https://www.bilibili.com/video/BV18B4y1K7Cs/?spm_id_from=333.999.0.0&vd_source=fa4ef8f26ae084f9b5f70a5f87e9e41b
事件
Qt主要用来开发带窗口的应用程序,我们使用的窗口的应用程序都是基于时间(比如安卓中的点击事件),其目的是实现回调(这样程序效率才高)
因此Qt为我们提供了一系列事件处理机制。
当窗口事件产生后,事件会经过事件派发->事件过滤->事件经过->事件处理四个阶段
Qt窗口中对一些列的事件都有一些默认的处理动作,如果我们有需要则要对这些事件进行重写
事件跟信号槽很像,个人理解是信号槽像事件的一部分
事件处理器函数
每个控件都有对应的事件处理器函数,要重写这些事件处理器函数则必须要用一个子类去继承QObject或者QWidget或者QWidget的子类,对这些事件处理器函数进行重写,这样我们就可以达到自己想要的效果。
通过官方文档中受保护的函数即可找到对应的时间函数,根据自己的需要重写即可
QEvent函数
注意:如果调用了ignore函数,则本窗口会对该事件忽略,并将这个事件向上传递给父窗口(Qt的窗口都是一层一层的),直到最外层窗口,若都没有处理,则这个事件就被Qt忽略掉了
重写事件小Demo
mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::closeEvent(QCloseEvent *ev)
{
//这个question自带两个按钮,一个yes,一个no
int ret = QMessageBox::question(this,"提问","您是否要关闭窗口");
if (ret == QMessageBox::Yes)
{
ev->accept();//接受事件
}
else
{
ev->ignore();//忽略事件
}
}
void MainWindow::resizeEvent(QResizeEvent *ev)
{
qDebug() << "oldsize: " << ev->oldSize() << "currentsize: " << ev->size();
}
自定义按钮
图片最好选择大小相差不大的,否则可能会出现显示不出来的情况
mybutton.h文件
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QWidget>
#include <QEvent>
#include<QMouseEvent>
class MyButton : public QWidget
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent *ev);
void enterEvent(QEvent* ev);
void leaveEvent(QEvent* ev);
void paintEvent(QPaintEvent *ev);//当窗口被刷新的时候,这个事件处理器函数自动被调用
private:
QPixmap m_pixmap; //专注显示图片,无法对图片进行像素级修改
// QImage m_img; //常用与多线程中绘图中像素级修改
signals:
};
#endif // MYBUTTON_H
mybutton.cpp文件
#include "mybutton.h"
#include <QPainter>
MyButton::MyButton(QWidget *parent)
: QWidget{parent}
{
m_pixmap.load(":/shark1.jpg");//先加载图1
setFixedSize(m_pixmap.size()); //将按钮的大小设为图片大小
}
void MyButton::mousePressEvent(QMouseEvent *ev)
{
m_pixmap.load(":/shark2.jpg");//按下加载第二张图片
update();
}
void MyButton::mouseReleaseEvent(QMouseEvent *ev)
{
m_pixmap.load(":/shark1.jpg");//释放加载回图1
update();//调用update函数会导致paintEvent函数被调用
}
void MyButton::enterEvent(QEvent *ev)
{
m_pixmap.load(":/shark3.jpg");//鼠标悬停加载图3
update();
}
void MyButton::leaveEvent(QEvent *ev)
{
m_pixmap.load(":/shark1.jpg");//离开加载图1
update();
}
void MyButton::paintEvent(QPaintEvent *ev)
{
//需要绘图要使用QPainter类,构造函数参数是指定绘图设备(即把图画到哪里,但是必须是一个绘图设备类)
//Qt中每个窗口都可以视为绘图设备类
QPainter painter(this);
painter.drawPixmap(rect(),m_pixmap);
}
注意:由于这个按钮控件是自定义控件,在完成对按钮的设计后需要,在ui文件进行添加
1.先找到自定义控件的父类
2.选择提升为
3.将自定义控件类名填进下面的这个地方
4.可以看到变成了Mybutton类型
为自定义按钮添加自定义信号
自定义信号
connect连接
运行结果
处理编译器的未使用参数的警告
1.直接把事件处理器函数中未用到的参数删掉
2.添加Q_UNUSED宏
结果:编译器未输出警告信息
注意
若自定义事件处理函数重写了父类的虚函数,则父类的虚函数就无法执行了
如果还想在子类中执行父类的虚函数该怎么做呢?
父类名直接访问对应的事件处理器函数,这样相当于在我们自定义的控件中处理了我们自定义的处理动作后,再进行父类对应处理动作的执行,看具体需求
如:这个自定义按钮继承的是QPushbutton类或其他按钮类,当这个按钮被点击时会发出一个clicked()信号,这时我们需要调用原本父类的mousePressEvent函数,这样这个信号才会被发射出去(即如果是继承的是QPushbutton类或其他按钮类则不需要自定义信号,只需要调用原本父类的事件处理器函数就能实现自定义信号的功能)