QT
大约 4 分钟
QT
目录
事件类 Event
鼠标事件 && 鼠标事件类
鼠标事件(各种)
头文件
#include <QMouseEvent>
具体查文档
- 鼠标进入,原型:
[virtual protected] void QWidget::enterEvent(QEvent *event);
- 鼠标离开,原型:
[virtual protected] void QWidget::leaveEvent(QEvent *event);
- 鼠标按下,原型:
[virtual void] void QLabel::mousePressEvent(QMouseEvent *ev);
- 鼠标释放,原型:
[virtual void] void QLabel::mouseReleaseEvent(QMouseEvent *ev);
- 鼠标按住移动,原型:
[virtual void] void QLabel::mouseMoveEvent(QMouseEvent *ev);
QMouseEvent
对象的公有方法
继承关系
QMouseEvent
父类为QInputEvent
,再父类为QEvent
QMouseEvent
常用公有方法的原型(详细查文档)
int x() const;
,x坐标,相对于局部控件而言int y() const;
,y坐标,相对于局部控件而言int globalX() const;
,x坐标,相对于屏幕分辨率而言int globalY() const;
,y坐标,相对于屏幕分辨率而言Qt::MouseButton button() const;
,返回按下的键所对应的媒体值- 常用媒体值:(具体查文档,非常多媒体值)
Qt::LeftButton
Qt::RightButton
Qt::MidButton
- 补充1
- 移动事件时会返回nobutton,需要使用
buttons()
方法
- 移动事件时会返回nobutton,需要使用
- 常用媒体值:(具体查文档,非常多媒体值)
Qt::MouseButtons buttons() const;
- 常用媒体值:(与瞬间值相比,这里可以有多个键同时按住)
Qt::LeftButton
:0x00000001(001)Qt::RightButton
:0x00000002(010)Qt::MidButton
:0x00000004(100)
- 补充1
- 判断时不能像button()一样用
==
,而需要使用按位与&
运算符 - 为什么这样设计?
&
可以轻易判断多个键同时按住的状态(只运算一个位而不是全部) - 比如
... & Qt::LeftButton & Qt::RightButton
- 判断时不能像button()一样用
- 补充2
- 可以设置鼠标追踪状态,
setMouseTracking(true);
- 然后不需要按下按键就会跟踪移动
- 可以设置鼠标追踪状态,
- 常用媒体值:(与瞬间值相比,这里可以有多个键同时按住)
鼠标实战 - 判断是否点击在指定区域
int width = this->width();
int height = mListWidget->height();
// 获取鼠标点击的区域,判断是否点在弹出框内
// x = 鼠标的屏幕像素坐标 - (莫名奇妙的坐标 - 控件的局部坐标),后者是控件坐上的屏幕像素坐标
// Global作用:将小部件坐标pos转换为全局屏幕坐标,不过结果有点奇怪就是
// 比较 x 是否在 0~width 之间
int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();
int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();
//qDebug()<<"1:"<<QCursor::pos().x();
//qDebug()<<"2:"<<mapToGlobal(geometry().topLeft()).x();
//qDebug()<<"3:"<<geometry().x();
if (x >= 0 && x <= width && y >= this->height() && y <= height + this->height())
{
//...
}
![mouseArea](04.%20事件函数 & 事件类.assets/mouseArea.png)
定时器事件 && 定时器类
方式一 timerEvent()
事件方法
原型:
[virtual protected] void QTimer::timerEvent(QTimerEvent *e);
使用:(省略原型定义)
构造函数 { /*返回值为定时器的标示,要在原型处声明以提高其作用域*/ int id1 = startTime(1000); // 启动定时器(每1s调用一次) int id2 = startTime(2000); // 启动定时器(每2s调用一次) } void Widget::timerEvent(QTimerEvent *) // 每隔一段时间调用一次这个方法 { if(ev->timerId() == id1) // 每1s被调用一次 { static int num 1= 1; // 静态变量,只会初始化一次 ui->label_1->setText(QString::number(num1++)); // 数值转字符串 } if(ev->timerId() == id2) // 每2s被调用一次 { static int num2 = 1; // 静态变量,只会初始化一次 ui->label_2->setText(QString::number(num2++)); // 数值转字符串 } }
方式二 QTimer
对象(面向对象方式,推荐)
QTimer * timer = new QTimer(this); // 创建定时器对象
timer->start(1000); // 启动定时器
connect(timer, &QTimer::timerout, [=](){/**/}); // 触发定时事件
// 多个定时任务时创建多个定时器对象即可
connect(ui->btn, &QPushButton::clicked, [=](){
timer->stop(); // 停止计时
timer->start(1000); // 重新启动
});
Event事件分发器 && 事件类【底层原理】
event()
事件分发器
原理
触发事件后,会由
event()
进行事件分发。判断是哪一种事件类型,然后自动触发对应的事件函数原型
bool event (QEvent *v);
用途
- 用于事件分发,也可以做拦截操作但不建议
返回值
- 如果是true则表示用户自己处理事件,不继续向下分发
使用示例
bool myLabel::event(QEvent *e) { if(e->type() == QEvent::MouseButtonPress) // 如果是鼠标按下,则处理并event事件分发中做拦截操作 { QMouseEvent * ev = static_cast<QMouseEvent *>(e) // 高级类型转换 QString str = QString("Event函数中,鼠标按下了,x=%1,y=%2".arg(ev.x).arg(ev.y)); qDebug() << str; return true; // 代表用户自己处理这个事件,不向下分发(此处不分发给mousePressEvent函数) } }
QEvent
对象
- 继承关系
QMouseEvent
父类为QInputEvent
,再父类为QEvent
- 常用枚举值
QEvent::None
,无,0QEvent::MouseButtonDbClick
,鼠标双击,4QEvent::MouseButtonPress
,鼠标按下,2QEvent::MouseButtonRelease
,鼠标释放,3
事件过滤器【底层】
原理
- 可以在程序分到
event事件分发器
前做一次高级拦截,优先度高于event()
- 可以在程序分到
原型
bool eventFilter(QObject *, QEvent *);
使用
(1) 给空间安装事件过滤器,
ui->label->installEventFilter(this);
(2) 重写
eventfilter
事件,eventFilter(QObject *obj, QEvent *e){}
bool eventFilter(QObject *obj, QEvent *e) { if(obj == ui->label && e->type() == QEvent::MouseButtonPress) // 如果是某对象和某方法时 { // return true; // 用户自己处理,不行给event()方法进行事件分发 } }