跳至主要內容

QT

LincZero大约 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()方法
  • Qt::MouseButtons buttons() const;
    • 常用媒体值:(与瞬间值相比,这里可以有多个键同时按住)
      • Qt::LeftButton:0x00000001(001)
      • Qt::RightButton:0x00000002(010)
      • Qt::MidButton:0x00000004(100)
    • 补充1
      • 判断时不能像button()一样用==,而需要使用按位与&运算符
      • 为什么这样设计?&可以轻易判断多个键同时按住的状态(只运算一个位而不是全部)
      • 比如... & Qt::LeftButton & Qt::RightButton
    • 补充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,无,0
    • QEvent::MouseButtonDbClick,鼠标双击,4
    • QEvent::MouseButtonPress,鼠标按下,2
    • QEvent::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()方法进行事件分发
          }
      }