0%

Qt事件机制

事件机制

QWidget::installEventFilter

当 obj 收到任何事件时,这些事件将首先被传递给 this(MyWidget)的 eventFilter 方法。

例如 btn->installEventFilter(this);

返回值:

if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.

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
class MyWidget : public QWidget
{
public:
explicit MyWidget() { this->installEventFilter(this); } // 注册事件过滤器

protected:
bool eventFilter(QObject *obj, QEvent *event) override
{
if (event->type()
== QEvent::MouseButtonPress) { // 每次鼠标按下就会触发(left,mid,right都会触发)
qDebug() << "eventfilter";
return true; // 阻止事件继续传播
}
return QWidget::eventFilter(obj, event); // 其他事件正常处理
}
bool event(QEvent *eve) override //filter happen before event
{
if (eve->type() == QEvent::MouseButtonPress)
qDebug() << "Event()";
return QWidget::event(eve);
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto *w = new MyWidget();
w->setGeometry(200, 200, 1000, 800);
w->show();
return a.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
QPushButton  {
min-height: 20px;
max-height: 60px;
margin: 5px;
padding: 20px;
margin:20px;
font-size: 20px;
color: white;
background-color: black;
border: 1px solid black;
border-radius:10px;
}

QPushButton:pressed{
color:green;
padding:20px;
margin:15px;
border-radius:10px;
}

事件传播

当MainWindow中的Gbutton发生mousePressEvent事件后,QPushButton默认实现不会传播到MainWindow的mousePressEvent,只有调用event->ignore();并且不能再调用QPushButton::mousePressEvent();否则仍然会accept();

那么我认为一切event先考虑设置成accept也就是不会传播,再考虑交给其他组件处理,这样保证不会出太大问题

才会传播到父组件,默认也就是event->accept();等价于 setAccepted(true)

通过event()函数编写处理代码是要通过返回值告诉调用者是否被接收,accept() or ignore() 没有意义

Calling accept() or ignore() on an event from event() is pointless

void GButton::mousePressEvent(QMouseEvent *e) {
e->ignore();
INFO(“[button]clicked”);
QPushButton::mousePressEvent(e); 如果调用基类的处理函数,那么会默认accept
}

Qt is designed in such a way that you normally never need to call them. The default value is “accept”, and the default event handler implementations in QWidget call ignore()

Qt 默认是accept也就是不会传播,但是QWidget的实现是ignore(),也就是会传播

Another Look at Events

qevent.html#ignore

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
namespace Ui {
class MainWindow;
}

QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

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

protected:
void mouseMoveEvent(QMouseEvent *event) override;
bool event(QEvent *e) override;
void mousePressEvent(QMouseEvent *) override;

private:
bool isMenuVisible;
void initMenu();
Ui::MainWindow *ui;
};
#include "mainwindow.h"
#include "gbutton.h"
#include "logger.h"
#include "ui_mainwindow.h"
#include <QMetaEnum>
#include <QMetaObject>
#include <QMouseEvent>
#include <QTimer>


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

btn->setParent(this);
btn->move(geometry().center() - btn->geometry().center());
INFO(__PRETTY_FUNCTION__);
initMenu();
setMouseTracking(true);
}

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

void MainWindow::mouseMoveEvent(QMouseEvent *event) {
// INFO(__PRETTY_FUNCTION__);
// INFO(rand());
QMainWindow::mouseMoveEvent(event);
}

bool MainWindow::event(QEvent *e) {
// QMetaObject meta = QEvent::staticMetaObject;
// QMetaEnum metaEnum = meta.enumerator(meta.indexOfEnumerator("Type"));

// // 使用QMetaEnum将枚举值转换为字符串
// QString eventType = metaEnum.valueToKey(e->type());

// // 输出事件类型字符串
// qDebug() << "[MainWindow]Event type:" << eventType;
// e->accept();
return QMainWindow::event(e);
}

void MainWindow::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
// 这里处理鼠标左键单击事件
qDebug() << "[mainwindow] left clicked";
}

return QMainWindow::mousePressEvent(event);
}

void MainWindow::initMenu() {
connect(ui->file_open_action, &QAction::triggered, this, [](bool check) {
INFO("file_open_action triggered " << (check ? "checked" : "unchecked"));
});
connect(ui->backup_action, &QAction::triggered, this, [](bool check) {
INFO("backup_action triggered" << (check ? "checked" : "unchecked"));
});
// connect(ui->menubar, &QMenuBar::hovered, this, [this](QAction *action) {
// INFO(action->text());
// auto menu = action->menu();

// menu->setIcon(QIcon(R"(C:\Project_repository\save\image\cat_640_640.jpg)"));
// });
}

#include <QPushButton>

class GButton : public QPushButton {
public:
explicit GButton();

protected:
bool event(QEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
};

#include "gbutton.h"
#include "logger.h"
#include <QMouseEvent>

GButton::GButton() {
setFixedSize({300, 100});
setText("button clicked");
}

bool GButton::event(QEvent *e) {
// INFO(__FUNCTION__);
return QPushButton::event(e);
}

void GButton::mousePressEvent(QMouseEvent *e) {
e->ignore();
INFO("[button]clicked");
}