本章要實(shí)現(xiàn)的整體效果如下:
QEvent::MouseButtonPress
? 鼠標(biāo)按下時(shí),觸發(fā)該事件,它對(duì)應(yīng)的子類是 QMouseEvent
QEvent::MouseMove
? 鼠標(biāo)移動(dòng)時(shí),觸發(fā)該事件,它對(duì)應(yīng)的子類是 QMouseEvent
QEvent::MouseButtonRelease
? 鼠標(biāo)釋放時(shí),觸發(fā)該事件,它對(duì)應(yīng)的子類是 QMouseEvent
本節(jié)通過(guò)兩個(gè)案例來(lái)講解這 3 個(gè)事件:
- 按下、移動(dòng)、釋放事件的基本使用
- 拖動(dòng)一個(gè)標(biāo)簽,使之移動(dòng)位置
1. 按下、移動(dòng)、釋放事件的基本使用
同樣使用上一節(jié)自定義的標(biāo)簽 LabelX
,來(lái)進(jìn)行講解
1.1 鼠標(biāo)按下、釋放事件
首先,來(lái)到 labelx.h
,聲明這 3 個(gè)函數(shù):
class LabelX : public QLabel
{
protected:
void mousePressEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev);
void mouseMoveEvent(QMouseEvent* ev);
};
然后,來(lái)到 labelx.cpp
實(shí)現(xiàn)這 3 個(gè)函數(shù):
void LabelX::mousePressEvent(QMouseEvent* ev)
{
// qDebug() << "mousePressEvent: " << ev->button() << ev->pos() << ev->globalPos();
if ( ev->button() == Qt::LeftButton ) {
qDebug() << "左鍵按下: " << "x=" << ev->x() << ", y=" << ev->y();
}
}
void LabelX::mouseReleaseEvent(QMouseEvent* ev)
{
// qDebug() << "mouseReleaseEvent: " << ev->button() << ev->pos() << ev->globalPos();
if ( ev->button() == Qt::LeftButton ) {
qDebug() << "左鍵釋放: " << "x=" << ev->x() << ", y=" << ev->y();
}
}
void LabelX::mouseMoveEvent(QMouseEvent* ev)
{
}
最后,來(lái)到 press_move_release_widget.cpp
,在構(gòu)造函數(shù)中添加 LabelX
控件,如下:
#include "labelx.h"
PressMoveReleaseWidget::PressMoveReleaseWidget(QWidget* parent) : QWidget{parent}
{
QVBoxLayout* verticalLayout = new QVBoxLayout(this);
verticalLayout->setSpacing(0);
verticalLayout->setContentsMargins(0, 0, 0, 0);
// 1. 添加一個(gè)自定義的標(biāo)簽 LabelX
LabelX* lblX = new LabelX(this);
lblX->setText("");
lblX->setFrameShape(QFrame::Box);
lblX->setFixedHeight(50);
lblX->setAlignment(Qt::AlignCenter);
lblX->setStyleSheet("background-color: blue;color: white;font-size: 25px");
verticalLayout->addWidget(lblX);
}
此時(shí)運(yùn)行程序,在標(biāo)簽上點(diǎn)擊時(shí),就會(huì)在控制臺(tái)打印按下還是釋放,并顯示點(diǎn)擊的位置:
1.2 鼠標(biāo)移動(dòng)事件
鼠標(biāo)移動(dòng),與鼠標(biāo)按下和釋放,在判斷按鍵時(shí)有些許不同
如果 mouseMoveEvent
實(shí)現(xiàn)如下:
void LabelX::mouseMoveEvent(QMouseEvent* ev)
{
qDebug() << "mouseMoveEvent: " << ev->button() << ev->pos() << ev->globalPos();
}
運(yùn)行結(jié)果如下:
我明明按下的是左鍵,但是打印的卻是沒有按鍵按下
因?yàn)?,此時(shí)不能使用 ev->button()
,而是要使用 ev->buttons()
,如下:
void LabelX::mouseMoveEvent(QMouseEvent* ev)
{
// 而是要用buttons()方法
qDebug() << "mouseMoveEvent: " << ev->buttons() << ev->pos() << ev->globalPos();
}
此時(shí),就可以正確打印了,如下:
可見,剛開始移動(dòng)只按左鍵,移動(dòng)過(guò)程中又按下了右鍵,也是可以識(shí)別到的。
在移動(dòng)過(guò)程中,判斷有左鍵按下的代碼,如下:
void LabelX::mouseMoveEvent(QMouseEvent* ev)
{
if ( ev->buttons() & Qt::LeftButton ) {
qDebug() << "左鍵移動(dòng)中: " << "x=" << ev->x() << ", y=" << ev->y();
}
}
這樣,鼠標(biāo)按下、移動(dòng)、釋放的整體效果,如下:
1.3 鼠標(biāo)跟蹤
以上,需要鼠標(biāo)保持按下的狀態(tài)下,系統(tǒng)才會(huì)調(diào)用 mouseMoveEvent
,實(shí)際工作中往往有這么一種需求:
鼠標(biāo)懸浮在控件上,而不是按下,就觸發(fā) mouseMoveEvent
事件,這怎么實(shí)現(xiàn)呢?
答案:設(shè)置鼠標(biāo)跟蹤,默認(rèn)情況下鼠標(biāo)跟蹤是關(guān)閉的,需要開啟
首先,來(lái)到 labelx.cpp
中,設(shè)置標(biāo)簽使能鼠標(biāo)跟蹤,如下:
LabelX::LabelX(QWidget* parent) : QLabel{parent}
{
this->setMouseTracking(true);
}
然后,在 mouseMoveEvent
中添加打印,如下:
void LabelX::mouseMoveEvent(QMouseEvent* ev)
{
qDebug() << "mouseMoveEvent: " << ev->buttons() << ev->pos() << ev->globalPos();
if ( ev->buttons() & Qt::LeftButton ) {
qDebug() << "左鍵移動(dòng)中: "
<< "x=" << ev->x() << ", y=" << ev->y();
}
}
此時(shí),在標(biāo)簽上懸浮移動(dòng)時(shí),也可以跟蹤到鼠標(biāo),如下:
2. 鼠標(biāo)事件移動(dòng)標(biāo)簽
接下來(lái),實(shí)現(xiàn)一個(gè)小案例:拖動(dòng)標(biāo)簽來(lái)移動(dòng)標(biāo)簽的位置
2.1 界面上添加標(biāo)簽
首先,在 press_move_release_widget.h
中添加成員變量:
#include <QLabel>
class PressMoveReleaseWidget : public QWidget
{
private:
QLabel* lbl;
QWidget* widget;
};
在 QLable
外邊套一層 QWidget
,是為了讓標(biāo)簽在這個(gè) widget
范圍內(nèi)移動(dòng)
然后,在 press_move_release_widget.cpp
的構(gòu)造中添加一個(gè)標(biāo)簽:
PressMoveReleaseWidget::PressMoveReleaseWidget(QWidget* parent) : QWidget{parent}
{
// ...
// 2. 添加一個(gè) QLabel
widget = new QWidget(this);
lbl = new QLabel(widget);
lbl->setText("");
lbl->setFrameShape(QFrame::Box);
lbl->setFixedSize(100, 100);
lbl->setStyleSheet("background-color: red;");
verticalLayout->addWidget(widget);
}
此時(shí),運(yùn)行效果如下:
2.2 為 QLabel 安裝事件過(guò)濾器
PressMoveReleaseWidget::PressMoveReleaseWidget(QWidget* parent) : QWidget{parent}
{
// ...
lbl->installEventFilter(this);
}
2.3 重寫 eventFilter() 函數(shù)
重寫當(dāng)前窗口的 eventFilter() 函數(shù)
首先,在 press_move_release_widget.h
文件中聲明該函數(shù),
同時(shí)聲明記錄窗口位置和鼠標(biāo)按下位置的變量,如下:
class PressMoveReleaseWidget : public QWidget
{
protected:
bool eventFilter(QObject* watched, QEvent* event);
private:
QPoint pressPos;
QPoint wndPos;
};
然后,在 press_move_release_widget.cpp
文件中實(shí)現(xiàn)該函數(shù),如下:
#include <QEvent>
#include <QMouseEvent>
#include <QDebug>
bool PressMoveReleaseWidget::eventFilter(QObject* watched, QEvent* event)
{
if ( watched != lbl ) {
return QWidget::eventFilter(watched, event);
}
if ( event->type() == QEvent::MouseButtonPress ) {
qDebug() << "MouseButtonPress";
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
pressPos = mouseEvent->globalPos();
wndPos = lbl->pos();
qDebug() << wndPos;
} else if ( event->type() == QEvent::MouseMove ) {
qDebug() << "MouseMove";
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
QPoint dstPos = wndPos + (mouseEvent->globalPos() - pressPos);
lbl->move(dstPos);
// 超出了最左邊
if ( lbl->pos().x() < 0 ) {
lbl->move(0, dstPos.y());
}
// 超出了最右邊
if ( lbl->pos().x() > widget->width() - lbl->width() ) {
lbl->move(widget->width() - lbl->width(), dstPos.y());
}
// 超出了最上邊
if ( lbl->pos().y() < 0 ) {
lbl->move(dstPos.x(), 0);
}
// 超出了最下邊
if ( lbl->pos().y() > widget->height() - lbl->height() ) {
lbl->move(dstPos.x(), widget->height() - lbl->height());
}
} else if ( event->type() == QEvent::MouseButtonRelease ) {
qDebug() << "MouseButtonRelease";
}
}
這里有些實(shí)現(xiàn)細(xì)節(jié),說(shuō)明如下:
- 如果不是 lbl 的事件,直接調(diào)用父類處理
return QWidget::eventFilter(watched, event)
- 在鼠標(biāo)按下時(shí),記錄
lbl
的位置和鼠標(biāo)按下位置,作為窗口移動(dòng)時(shí)的參考 - 當(dāng)
lbl
超出 widget 邊界時(shí),讓它等于邊界值
此時(shí),就可以通過(guò)鼠標(biāo)拖動(dòng)標(biāo)簽,在 widget
范圍內(nèi)移動(dòng)了,如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-719954.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-719954.html
到了這里,關(guān)于【QT開發(fā)筆記-基礎(chǔ)篇】| 第四章 事件QEvent | 4.4 鼠標(biāo)按下、移動(dòng)、釋放事件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!