本篇演示了下面的内容:
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
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路


















