事件处理

QT中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等。QT中,任何QObject子类示例都可以接收和处理事件。实际编程中通常实现部件的paintEvent()、mousePressEvent()等事件处理函数来处理特定部件的特定事件。

每个程序的main函数最后都会调用QApplication类的exec()函数,它会使QT应用程序进入到事件循环,使应用程序在运行的时候接收各种事件。一旦有事件发生,QT便会构造一个相应的QEvent子类的对象来表示它,然后将它传递给QObject对象或子对象。

image-20220219223151174


鼠标事件

对鼠标实现进行重写来实现你想要达到的功能

mouseevent.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef MOUSEEVENT_H
#define MOUSEEVENT_H

#include <QMainWindow>
#include<QLabel>
#include<QMouseEvent>
namespace Ui {
class MouseEvent;
}

class MouseEvent : public QMainWindow
{
Q_OBJECT

public:
explicit MouseEvent(QWidget *parent = 0);
~MouseEvent();
protected:
void mousePressEvent(QMouseEvent *event);//鼠标按下
void mouseMoveEvent(QMouseEvent *event);//鼠标移动
void mouseReleaseEvent(QMouseEvent *event);//鼠标释放
private:
Ui::MouseEvent *ui;
QLabel *m_statusLabel;
QLabel* m_posLabel;
};

#endif // MOUSEEVENT_H

mouseevent.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "mouseevent.h"
#include "ui_mouseevent.h"

MouseEvent::MouseEvent(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MouseEvent)
{
ui->setupUi(this);
setWindowTitle(QString("鼠标事件"));
m_statusLabel = new QLabel(QString("当前位置:"));
m_statusLabel->setFixedWidth(100);

m_posLabel = new QLabel(QString(""));
m_posLabel->setFixedWidth(100);

statusBar()->addPermanentWidget(m_statusLabel);//状态栏添加永久部件
statusBar()->addPermanentWidget(m_posLabel);
}

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

void MouseEvent::mousePressEvent(QMouseEvent *event)
{
QString str = "("+QString::number(event->x())+","+QString::number(event->y())+")";
if(event->button() == Qt::LeftButton)
{
statusBar()->showMessage(QString("左键:") +str );
}
else if(event->button() == Qt::MidButton)
{
statusBar()->showMessage(QString("中键:")+str);
}
else if(event->button() == Qt::RightButton)
{
statusBar()->showMessage(QString("右键")+str);
}
}

void MouseEvent::mouseMoveEvent(QMouseEvent *event)
{
QString strPos;
strPos = "(" + QString::number(event->x())+","+QString::number(event->y())+")";
m_posLabel->setText(strPos);
}

void MouseEvent::mouseReleaseEvent(QMouseEvent *event)
{
QString strPos;
strPos = "(" + QString::number(event->x())+","+QString::number(event->y())+")";
statusBar()->showMessage(QString("释放在:")+strPos,3000);
}

image-20220220112246657


键盘事件

通过重写键盘事件来达到你想要实现的效果

keyevent.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef KEYEVENT_H
#define KEYEVENT_H

#include <QWidget>
#include<QKeyEvent>
namespace Ui {
class KeyEvent;
}

class KeyEvent : public QWidget
{
Q_OBJECT

public:
explicit KeyEvent(QWidget *parent = 0);
~KeyEvent();
void drawPix();
void keyPressEvent(QKeyEvent *event) override;
void paintEvent(QPaintEvent* event)override;

private:
Ui::KeyEvent *ui;
QPixmap *m_pix;
QImage m_image;
int m_startX; //图标顶点位置
int m_startY;
int m_width; //界面的宽度,高度
int m_height;
int m_step; //步长

};

#endif // KEYEVENT_H

keyevent.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "keyevent.h"
#include "ui_keyevent.h"
#include<QPainter>
#include<QPen>
KeyEvent::KeyEvent(QWidget *parent) :
QWidget(parent),
ui(new Ui::KeyEvent)
{
ui->setupUi(this);
setWindowTitle(QString("键盘事件"));
setAutoFillBackground(true);
setFixedSize(521,256);
m_width = size().width();
m_height = size().height();
m_pix = new QPixmap(m_width,m_height);
m_pix->fill(Qt::white);
m_image.load("picture.jpg");
m_startX = 100;
m_startY = 100;
m_step = 20;
drawPix();

}

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

void KeyEvent::drawPix()
{
m_pix->fill(Qt::white);
QPainter painter(this);
QPen pen(Qt::DotLine);
//按照步长画纵向网格线
//bagin与end成对出现
for(int i = m_step;i < m_width; i+=m_step)
{
painter.begin(m_pix);//指定m_pix为绘图设备
painter.setPen(pen);//设置笔
painter.drawLine(QPoint(i,0),QPoint(i,height()));
painter.end();
}
//按照步长画水平网格线
for(int j = m_step;j < m_height;j += m_step)
{
painter.begin(m_pix);//指定m_pix为绘图设备
painter.setPen(pen);//设置笔
painter.drawLine(QPoint(0,j),QPoint(m_width,j));
painter.end();
}
//画图片
painter.begin(m_pix);
painter.drawImage(QPoint(m_startX,m_startY),m_image);
painter.end();
}

void KeyEvent::keyPressEvent(QKeyEvent *event)
{
//按下ctrl,每次移动为1个像素
if(event->modifiers() == Qt::ControlModifier)
{
if(event->key() == Qt::Key_Left)
{
m_startX = (m_startX -1)<0 ? m_startX : m_startX-1;
}
if(event->key() == Qt::Key_Right)
{
m_startX = (m_startX +1+m_image.width()) > m_width ? m_startX :m_startX+1 ;
}
if(event->key() == Qt::Key_Up)
{
m_startY = (m_startY - 1) < 0 ? m_startY:m_startY -1;
}
if(event->key() == Qt::Key_Down)
{
m_startY = (m_startY +1 +m_image.height()) > m_height ? m_startY:m_startY+1;
}
}
else//没有按ctrl键,每一移动为一个步长
{
//调整图标左上角位置到网格顶点顶点上
m_startX = m_startX - m_startX % m_step;
m_startY =m_startY - m_startY % m_step;
if(event->key() == Qt::Key_Left)
{
m_startX = (m_startX -m_step)<0 ? m_startX : m_startX-m_step;
}
if(event->key() == Qt::Key_Right)
{
m_startX = (m_startX +m_step+m_image.width()) > m_width ? m_startX :m_startX+m_step ;
}
if(event->key() == Qt::Key_Up)
{
m_startY = (m_startY - m_step) < 0 ? m_startY:m_startY -m_step;
}
if(event->key() == Qt::Key_Down)
{
m_startY = (m_startY +m_step +m_image.height()) > m_height ? m_startY:m_startY+m_step;
}
}
drawPix();//根据调整后的图标位置重新在m_pix上绘制图像
update();//触发窗口重绘
}

void KeyEvent::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
painter.drawPixmap(QPoint(0,0),*m_pix);
painter.end();
}

image-20220220182327142


事件过滤

指定某个对象对什么事件进行处理。

示例:鼠标按压对指定图片进行缩放

dialog.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QLabel>
#include<QImage>
#include<QHBoxLayout>
#include<QEvent>
#include<QMouseEvent>

class Dialog : public QDialog
{
Q_OBJECT

public:
Dialog(QWidget *parent = 0,Qt::WindowFlags f = 0);
~Dialog();
public slots:
bool eventFilter(QObject*watched ,QEvent *event)override;
private:
QLabel *m_label1;
QLabel *m_label2;
QLabel *m_label3;
QLabel *m_stateLabel;

QImage m_image1;
QImage m_image2;
QImage m_image3;


};

#endif // DIALOG_H

dialog.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "dialog.h"
#include<QHBoxLayout>

Dialog::Dialog(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(QString("事件过滤"));

m_label1 = new QLabel;
m_label2 =new QLabel;
m_label3 = new QLabel;
m_stateLabel = new QLabel(QString("鼠标按下标志"));



m_stateLabel->setAlignment(Qt::AlignHCenter);//水平居中

m_image1.load("fly1.png");
m_image2.load("fly2.png");
m_image3.load("fly3.png");

m_label1->setPixmap(QPixmap::fromImage(m_image1));
m_label2->setPixmap(QPixmap::fromImage(m_image2));
m_label3->setPixmap(QPixmap::fromImage(m_image3));
//添加水平布局
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_label1);
layout->addWidget(m_label2);
layout->addWidget(m_label3);


QVBoxLayout*mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addWidget(m_stateLabel);

resize(m_image2.width() * 3,m_image2.height() *2);

//给图片标签部件安装事件过滤,并且指定整个窗体为监视事件的对象。
m_label1->installEventFilter(this);
m_label2->installEventFilter(this);
m_label3->installEventFilter(this);


}

Dialog::~Dialog()
{

}

//对象-事件
bool Dialog::eventFilter(QObject *watched, QEvent *event)
{
QMatrix matrix;//放大比例
QImage tmpImg;//保存处理过后的图片

//放大图片
matrix.scale(2.0,2.0);
//对象
if(watched == m_label1)
{
//鼠标按下事件的处理
if(event->type() == QEvent::MouseButtonPress)
{
//转换事件类型Wie鼠标事件
QMouseEvent* mouseEvent = (QMouseEvent*)event;
if(mouseEvent->button() & Qt::LeftButton)
{
m_stateLabel->setText(QString("左键按下图片1"));
}
if(mouseEvent->button() & Qt::MidButton)
{
m_stateLabel->setText(QString("中键按下图片1"));
}
if(mouseEvent->button() & Qt::RightButton)
{
m_stateLabel->setText(QString("右键按下图片1"));
}
//将原本图片缩放用tmpImg临时存储,设置图片
tmpImg = m_image1.transformed(matrix);
m_label1->setPixmap(QPixmap::fromImage(tmpImg));
}
//鼠标释放,恢复图片大小
if(event->type() == QEvent::MouseButtonRelease)
{
m_stateLabel->setText(QString("鼠标释放图片1"));
m_label1->setPixmap(QPixmap::fromImage(m_image1));
}
}
else if(watched ==m_label2)
{
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = (QMouseEvent*)event;
if(mouseEvent->button() & Qt::LeftButton)
{
m_stateLabel->setText(QString("左键按下图片2"));
}
if(mouseEvent->button() & Qt::MidButton)
{
m_stateLabel->setText(QString("中键按下图片2"));
}
if(mouseEvent->button() & Qt::RightButton)
{
m_stateLabel->setText(QString("右键按下图片2"));
}
tmpImg = m_image2.transformed(matrix);
m_label2->setPixmap(QPixmap::fromImage(tmpImg));
}
if(event->type() == QEvent::MouseButtonRelease)
{
m_stateLabel->setText(QString("鼠标释放图片2"));
m_label2->setPixmap(QPixmap::fromImage(m_image2));
}
}
else if(watched ==m_label3)
{
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* mouseEvent = (QMouseEvent*)event;
if(mouseEvent->button() & Qt::LeftButton)
{
m_stateLabel->setText(QString("左键按下图片3"));
}
if(mouseEvent->button() & Qt::MidButton)
{
m_stateLabel->setText(QString("中键按下图片3"));
}
if(mouseEvent->button() & Qt::RightButton)
{
m_stateLabel->setText(QString("右键按下图片3"));
}
tmpImg = m_image3.transformed(matrix);
m_label3->setPixmap(QPixmap::fromImage(tmpImg));
}
if(event->type() == QEvent::MouseButtonRelease)
{
m_stateLabel->setText(QString("鼠标释放图片3"));
m_label3->setPixmap(QPixmap::fromImage(m_image3));
}
}

//事件交给上层对话框进行处理
return QDialog::eventFilter(watched,event);
}