4. QT中的事件函数 --- 鼠标事件、键盘事件、定时器事件、绘图事件

1. 说明

在QT的控件或者窗口当中,如果对于当前鼠标或者键盘的功能需要自己定义,可以重写父类当中对应虚函数,主要包括以下几个:

//键盘按键按下
virtual void keyPressEvent(QKeyEvent *event);
//键盘按键抬起
virtual void keyReleaseEvent(QKeyEvent *event);
//鼠标离开
virtual void leaveEvent(QEvent *event);
//鼠标双击
virtual void mouseDoubleClickEvent(QMouseEvent *event);
//鼠标移动
virtual void mouseMoveEvent(QMouseEvent *event);
//鼠标按下
virtual void mousePressEvent(QMouseEvent *event);
//鼠标抬起
virtual void mouseReleaseEvent(QMouseEvent *event);
//鼠标滚轮事件
virtual void wheelEvent(QWheelEvent *event);

2. 相关代码

使用鼠标移动时,需要在构造函数中开启鼠标追踪

this->setMouseTracking(true);

键盘响应代码:

void Widget::keyPressEvent(QKeyEvent *event)
{
    
    
    switch (event->key()) {
    
    
    case Qt::Key_W:
        qDebug()<<"模型前进...";
        break;
    case Qt::Key_S:
        qDebug()<<"模型后退...";
        break;
    case Qt::Key_A:
        qDebug()<<"模型向左...";
        break;
    case Qt::Key_D:
        qDebug()<<"模型向右...";
        break;
    default:
        break;
    }
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    
    
    switch (event->key()) {
    
    
    case Qt::Key_W:
        qDebug()<<"模型停止前进...";
        break;
    case Qt::Key_S:
        qDebug()<<"模型停止后退...";
        break;
    case Qt::Key_A:
        qDebug()<<"模型停止向左...";
        break;
    case Qt::Key_D:
        qDebug()<<"模型停止向右...";
        break;
    default:
        break;
    }
}

鼠标按键响应事件:

void Widget::enterEvent(QEvent *event)
{
    
    
    Q_UNUSED(event);
    qDebug()<<"鼠标进入...";
}

void Widget::leaveEvent(QEvent *event)
{
    
    
    Q_UNUSED(event);
    qDebug()<<"鼠标离开...";
}

void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
    
    
    //判断鼠标按键类型
    if(event->button() == Qt::LeftButton){
    
    
        qDebug()<<event->pos();
        qDebug()<<"鼠标双击...";
    }
    
}

3. 鼠标位置

QMouseEvent中有两种获取鼠标位置的函数,相关解释如下:

void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
    
    
    //判断鼠标按键类型
    if(event->button() == Qt::LeftButton){
    
    
        
        qDebug()<<event->pos();//输出的是鼠标在相对于本控件左上角的位置
        
        qDebug()<<event->globalPos();//输出的是鼠标相对于整个显示器窗口左上角的位置
        
        qDebug()<<"鼠标双击...";
    }
}

案例:鼠标拖动图片移动
相关位置计算辅助记忆:
在这里插入图片描述
在Qt中显示一张图片,是使用QLabel控件来装载QPixmap图像源,如果图片控件需要支持鼠标的拖拽移动,需要自己定义一个控件,然后重新其父类的鼠标控制相关函数。
所以,先定义一个C++的类,继承QLabel,重写其 mousePressEvent 和 mouseMoveEvent 类,相关代码如下:
ImageLabel.h:

#ifndef IMAGELABEL_H
#define IMAGELABEL_H

#include <QObject>
#include <QLabel>
#include <QWidget>
#include <QPixmap>

class ImageLabel : public QLabel
{
    
    
    Q_OBJECT
public:
    explicit ImageLabel(const QPixmap &pix,QWidget* parent = nullptr);

    //重写虚函数
    virtual void mousePressEvent(QMouseEvent* event) override;
    virtual void mouseMoveEvent(QMouseEvent* event) override;
    //重写键盘控制函数
    virtual void keyPressEvent(QKeyEvent* event) override;

private:
    QPoint mousePressPos;//鼠标点击位置
    int mSpeed;//控制移动速度
	
signals:

};

#endif // IMAGELABEL_H

ImageLabel.cpp:

#include "imagelabel.h"
#include <QMouseEvent>

ImageLabel::ImageLabel(const QPixmap &pix, QWidget *parent)
{
    
    
    //设置图像源
    this->setPixmap(pix);
    //设置父控件
    this->setParent(parent);
    //设置图像比例填充
    this->setScaledContents(true);
    this->mSpeed = 10;
    //处理键盘事件需要先获取焦点
    this->setFocusPolicy(Qt::StrongFocus);
}

void ImageLabel::mousePressEvent(QMouseEvent *event)
{
    
    
    //记录鼠标开始点击时的初始位置向量
    mousePressPos = event->pos();
}

void ImageLabel::mouseMoveEvent(QMouseEvent *event)
{
    
    
    //求鼠标移动偏移量(向量)
    QPoint deltaMove = event->pos() - mousePressPos;
    //此时鼠标移动了,但是控件本身位置还没有加上偏移量,还未移动
    //求窗口新位置(当前位置 + 偏移量)
    this->move(this->pos() + deltaMove);
}
void ImageLabel::keyPressEvent(QKeyEvent *event)
{
    
    
    qDebug()<<"123";
    switch (event->key()) {
    
    
        case Qt::Key_W:{
    
    
            QPoint pos = this->pos() + QPoint(0,-1) * mSpeed;
            this->move(pos);
            break;
        }
        case Qt::Key_S:{
    
    
            QPoint pos = this->pos() + QPoint(0,1) * mSpeed;
            this->move(pos);
            break;
        }
        case Qt::Key_A:{
    
    
            QPoint pos = this->pos() + QPoint(-1,0) * mSpeed;
            this->move(pos);
            break;
        }
        case Qt::Key_D:{
    
    
            QPoint pos = this->pos() + QPoint(1,0) * mSpeed;
            this->move(pos);
            break;
        }
    }

}

然后再在主窗口中使用自定义类创建图片控件即可:

//使用label在窗口上添加一个图片
QPixmap piximg(":/imgs/images/tt.png");
ImageLabel *imgLab = new ImageLabel(piximg,this);
imgLab->move(50,100);//定义初始位置

效果展示:

鼠标键盘移动自定义控件

4. 定时器事件

如果想每间隔一段时间就去做某件事情,可以重写定时器事件函数,实例代码如下:
widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    
    
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    
protected:
    //重写父类的定时器虚函数
    virtual void timerEvent(QTimerEvent* event) override;
    
private:
    //声明两个变量,用于接收定时器的ID号
    int playerTimerID;
    int monsterTimerID;
    
    
};
#endif // WIDGET_H

widget.cpp:

#include "widget.h"
#include <QDebug>
#include <QTimerEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    
    
    //开启玩家定时器
    playerTimerID = this->startTimer(1000);
    //开启怪物定时器
    monsterTimerID = this->startTimer(2000);

	//除了使用startTimer外,也可以使用QTimer类定义定时器对象实现
}

Widget::~Widget()
{
    
    
}

void Widget::timerEvent(QTimerEvent *event)
{
    
    
    if(event->timerId() == this->playerTimerID){
    
    
        qDebug()<< "玩家定时器被触发...";
    }
    if(event->timerId() == this->monsterTimerID){
    
    
        qDebug()<< "怪物定时器被触发...";
    }
}

5. 绘图事件

Qt中的绘图事件函数可以绘制各种图像,比如图片或者自定义的形状等,需要重写父类的paintEvent函数,示例代码如下:
widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPainter>
#include <QColor>
#include <QTimer>

class Widget : public QWidget
{
    
    
    Q_OBJECT

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

protected:
    //重写父类的绘图事件函数
    virtual void paintEvent(QPaintEvent* event) override;

private:
    //声明一个画家(在一个画布中是可以设置多个画家的)
    QPainter* mPainter;
    //绘制更新定时器
    QTimer* mTimer;

};
#endif // WIDGET_H

widget.cpp:

#include "widget.h"
#include <QDebug>
#include <QTimerEvent>
#include <QColorDialog>
#include <QPixmap>
#include <QImage>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    
    
    //初始化画家
    mPainter = new QPainter(this);
    mTimer= new QTimer(this);
    mTimer->start(100);
    //绘画事件有一个update()函数,当画布发生了新的绘制时,应该调用这个函数让画布更新,这里采用定时器进行刷新
    connect(mTimer,&QTimer::timeout,[this](){
    
    this->update();});
}

Widget::~Widget()
{
    
    
}

void Widget::paintEvent(QPaintEvent *event)
{
    
    
    /*画家准备工作*/
    //创建画笔
    QPen pen(QColor(0,0,125));
    //给画家添加画笔
    mPainter->setPen(pen);
    //开启绘制
    mPainter->begin(this);//即使有多个画家存在,这个开始函数也只需要其中一个画家调用一次就行了

    //开始绘制直线
    mPainter->drawLine(0,0,100,100);

    //绘制矩形
    mPainter->drawRect(100,100,200,50);

    //绘制椭圆
    mPainter->drawEllipse(150,150,50,25);

    //绘制图片
    QImage img(":/imgs/imgs/girl.jpg");
    mPainter->translate(100,200);//画家平移
    mPainter->rotate(45.0);//画家旋转
    mPainter->drawImage(QRect(0,0,100,100),img);
    mPainter->drawImage(QRect(0,0,200,200),img,QRect(200,0,200,200));//指定绘制区域位置
    /*
        第一个参数:(0,0)代表图片的左上角,(200,200)设定图片的大小
        第二个参数:图片源
        第三个参数:(200,0)指定在整张图片上选择的开始绘制点,(200,200)指绘制的尺寸
    */
    
    //结束绘制
    mPainter->end();
}

猜你喜欢

转载自blog.csdn.net/FY_13781298928/article/details/130763310