本篇演示了下面的内容:
QLabel中鼠标常用事件
定时器的二种实现方式
负责事件分发的event事件
负责事件过滤的eventFilter
下面的演示代码中,界面上第一个label是一个提升为Mylabel类的自定义控件.
其它的是普通的label
MyLable.h
#pragma once #pragma execution_character_set("utf-8") #include "qlabel.h" class MyLable : public QLabel { Q_OBJECT public: MyLable(QWidget *parent); ~MyLable(); //这两个是继承自QWidget类都有的事件 void enterEvent(QEvent *); void leaveEvent(QEvent *); //下面三个是继承自QLable类的独有事件 void mouseMoveEvent(QMouseEvent *ev); void mousePressEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent *ev); bool event(QEvent *ev); };
MyLable.cpp
#include "MyLable.h" #include <qdebug.h> #include <QMouseEvent> MyLable::MyLable(QWidget *parent): QLabel(parent) { } MyLable::~MyLable() { } void MyLable::enterEvent(QEvent *e){ qDebug() << "鼠标进入了..."; } void MyLable::leaveEvent(QEvent *e){ qDebug() << "鼠标离开了..."; } void MyLable::mouseMoveEvent(QMouseEvent *ev){ //持续状态,要用buttons 用与操作符进行判断 //大家可以试试不要这个if的对比效果 if (ev->buttons() & Qt::LeftButton){ //按下左键的情况下才会输出下面信息 QString msg = QString("鼠标移动了... x=%1,y=%2").arg(ev->x()).arg(ev->y()); qDebug() << msg; } } void MyLable::mousePressEvent(QMouseEvent *ev){ if (ev->button() == Qt::LeftButton){ qDebug() << "鼠标按下了..."; } } void MyLable::mouseReleaseEvent(QMouseEvent *ev){ if (ev->button() == Qt::LeftButton){ qDebug() << "鼠标松开了..."; } } //event事件负责全部事件的分发工作,勇哥理解相当于消息环境中的case处理 bool MyLable::event(QEvent *ev){ if (ev->type() == QEvent::MouseButtonPress){ QMouseEvent * e = static_cast<QMouseEvent *>(ev); QString str = QString("Event: 鼠标按下 x=%1 y=%2").arg(e->x()).arg(e->y()); qDebug() << str; //只有鼠标扫下事件自己处理 return true; } //其它事件交给父类处理 return QLabel::event(ev); }
QtForOpencv.h
#pragma once #pragma execution_character_set("utf-8") #include <QtWidgets/QWidget> #include "ui_QtForOpencv.h" #include <QLabel> class QtForOpencv : public QWidget { Q_OBJECT public: QtForOpencv(QWidget *parent = Q_NULLPTR); void timerEvent(QTimerEvent *e); bool eventFilter(QObject *, QEvent *); private: Ui::QtForOpencvClass ui; int id1=0; int id2=0; public: QLabel* imgLabel; };
QtForOpencv.cpp
#include "QtForOpencv.h" #include <opencv2\opencv.hpp> #include <opencv2\core.hpp> #include <opencv2\imgcodecs.hpp> #include <opencv2\imgproc.hpp> #include <qtimer.h> #include <qevent.h> #include <qdebug.h> using namespace cv; using namespace std; QtForOpencv::QtForOpencv(QWidget *parent) : QWidget(parent) { ui.setupUi(this); id1=startTimer(1000); id2 = startTimer(200); //第二种订时器的办法 QTimer * t1 = new QTimer(this); t1->start(500); connect(t1, &QTimer::timeout, [=](){ static long num = 0; ui.labTimer3->setText(QString::number(num++)); }); //点按钮后暂t1 connect(ui.btnStop, &QPushButton::clicked, [=]{ t1->stop(); }); //事件过滤器用法 //步骤1:先给控件安装过滤器 ui.label->installEventFilter(this); //步骤2:重写eventFilter事件 waitKey(0); } void QtForOpencv::timerEvent(QTimerEvent *e){ //第一种订时器的方式,利用timerEvent事件 static long num = 0; static long num2 = 0; if (e->timerId() == id1){ ui.labTimer->setText(QString::number(num++)); } else if (e->timerId() == id2){ ui.labTimer2->setText(QString::number(num2++)); } } //重写eventFilter事件 bool QtForOpencv::eventFilter(QObject * obj, QEvent * ev){ if (obj == ui.label) { if (ev->type() == QEvent::MouseButtonPress){ QMouseEvent * e = static_cast<QMouseEvent *>(ev); QString str = QString("EventFilter: 鼠标按下 x=%1 y=%2").arg(e->x()).arg(e->y()); qDebug() << str; //只有鼠标扫下事件自己处理 return true; } } //其它事件交给父类处理 return QWidget::eventFilter(obj,ev); }
运行结果见下图.
第一个lable用于重写一些鼠标有关的事件, 可以在vs的信息栏看到这个事件输出信息.
其它几个lable 演示了定时器的用法.
代码说明:
(1) 订时器的实现方式有两种,一是利用timerEventg事件,另一种跟C#类似,使用一个QTimer类来实现.
(2) event事件主要是负责事件的分发,有点像win32里面的消息循环中的case处理
eventFilter是事件过滤器, 负责处理顶层消息拦截, 这个有点像是win32里面的消息勾子.
它的关系是这样的:
(3) 所有控件都有可以被重写的消息, 上面例子里, 重写了lable的如下图所示的一些方法.
在vs的环境下, 重写这些方法时, 参数无法自动补全,这个真是意料之外的事.
所以最好查看QT的帮助, 复制它的函数定义来得快些.
再接下来勇哥想研究一下文件读写与数据流, 这些在工控软件里面用于写入客户需要的生产数据, 是常用的东东.
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

