最近决定学习一下Qt了,主要有一下原因:
1、同MFC相比Qt应该是一个简单易用的C++类库了。特别是Qt5开始他把串口的通信甚至Modbus的通信都做成了类,这是给工控开发人员提供了极大的方便,又可以少造点*。
2、MFC及Qt的对比使用,也能增强对基础的理解。
用halcon结合Qt做视觉第一个问题是环境的配置:
#includes
INCLUDEPATH += "$$(HALCONROOT)/include"
INCLUDEPATH += "$$(HALCONROOT)/include/halconcpp"
#libs
QMAKE_LIBDIR += "$$(HALCONROOT)/lib/$$(HALCONARCH)"
win32: LIBS += halconcpp.lib
开发视觉系统,第一个要解决的小程序,恐怕就是图像在GUI上的更新了。作为一个视觉系统,不更新实时显示,元芳你怎么看?
定时器或线程手段就是用来解决这个问题的。 经过各种资料的搜刮可知,定时器方案又分为:1、QObject类的定时器, 2、定时器类QTimer。线程方案又有四种:1、继承QThread、2、继承QRunnable、3、使用moveToThread、4、使用QtConcurrent::run;
还有个小问题是,如何将图形窗口嵌入对话框内。需要将halcon的 WindowHandle 同控件的 winId关联起啦。
关于QObject类的定时器
QObject是所有Qt对象的基类,它提供了一个基本的定时器。
通过QObject::startTimer(),可以把一个一毫秒为单位的时间间隔作为参数来开始定时器,这个函数
返回一个唯一的整数定时器的标识符。这个定时器开始就会在每一个时间间隔"触发",直到明确的使用这个定时器的标识符来调用QObject::
killTimer()结束。
当定时器触发时,应用程序会发送一个QTimerEvent。 在事件循环中,处理器按照事件队列的顺序来处理定时器事件。当处理器正忙于其它事件处理时,定时器就不能立即处理。
与定时器相关的成员函数有:startTimer()、timeEvent()、killTimer()。QObject基类中的startTimer()和timerEvent()原型及说明如下:
intQObject::startTimer(int interval);
开始一个定时器并返回定时器ID,如果不能开始一个定时器,将返回0。定时器开始后,每隔interval毫秒间隔将触发一次超时事件,直到killTimer()被调用来删除定时器。 如果interval为0,那么定时器事件每次发生时没有窗口系统事件处理。
virtual voidQObject::timerEvent(QTimerEvent *event);
虚函数timerEvent()被重载来实现用户的超时事件处理函数。如果有多个定时器在运行,QTimerEvent::timerId()被用来查找指定定时器,对其进行操作。
当定时器事件发生时,虚函数timerEvent()随着QTimerEvent事件参数类一起被调用,重载这个函数可以获得定时器事件。
当定时器触发时,应用程序会发送一个QTimerEvent。 在事件循环中,处理器按照事件队列的顺序来处理定时器事件。当处理器正忙于其它事件处理时,定时器就不能立即处理。
与定时器相关的成员函数有:startTimer()、timeEvent()、killTimer()。QObject基类中的startTimer()和timerEvent()原型及说明如下:
intQObject::startTimer(int interval);
开始一个定时器并返回定时器ID,如果不能开始一个定时器,将返回0。定时器开始后,每隔interval毫秒间隔将触发一次超时事件,直到killTimer()被调用来删除定时器。 如果interval为0,那么定时器事件每次发生时没有窗口系统事件处理。
virtual voidQObject::timerEvent(QTimerEvent *event);
虚函数timerEvent()被重载来实现用户的超时事件处理函数。如果有多个定时器在运行,QTimerEvent::timerId()被用来查找指定定时器,对其进行操作。
当定时器事件发生时,虚函数timerEvent()随着QTimerEvent事件参数类一起被调用,重载这个函数可以获得定时器事件。
使用该方法打开相机步骤:
1、在UI设计器中拖入一个label,一个checkbox(continueGrabCheckBox)
2、将checkbox的信号(clicked(bool))与widget的槽(
imgGrabStartOrStop
(
bool
))链接
3、其他部分代码如下
widget.h文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "HalconCpp.h"
using namespace HalconCpp;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void timerEvent(QTimerEvent *);
private:
Ui::Widget *ui;
int imgShowTimerId;
private slots:
void imgGrabStartOrStop(bool flag);
public:
HObject ho_Image;
HTuple hv_AcqHandle;
HTuple hv_Width, hv_Height, hv_WindosID;
Hlong winID;
};
#endif // WIDGET_H
widget.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#define fpsOfCamera 35
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
winID = (Hlong)ui->imageShowLabel->winId();
SetCheck("~father");
OpenWindow(0,0,(Hlong)ui->imageShowLabel->width(),(Hlong)ui->imageShowLabel->height(),winID,"","",&hv_WindosID);
SetCheck("father");
}
Widget::~Widget()
{
delete ui;
}
void Widget::imgGrabStartOrStop(bool flag)
{
if(flag)
{
qDebug()<<"Started grabing";
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false",
"default", "[0] Lenovo EasyCamera", 0, -1, &hv_AcqHandle);
GrabImage(&ho_Image, hv_AcqHandle);
GetImageSize(ho_Image,&hv_Width,&hv_Height);
SetPart(hv_WindosID,0,0,hv_Height-1,hv_Width-1);
imgShowTimerId = startTimer(1000/fpsOfCamera);
qDebug()<<"imgShowTimerId:"<<imgShowTimerId;
}
else
{
qDebug()<<"stoped grabing! imgShowTimerId:"<<imgShowTimerId;
killTimer(imgShowTimerId);
CloseFramegrabber(hv_AcqHandle);
}
}
void Widget::timerEvent(QTimerEvent *event)
{
if(event->timerId())
{
GrabImage(&ho_Image, hv_AcqHandle);
DispObj(ho_Image,hv_WindosID);
qDebug()<<"event->timerId():"<<event->timerId();
}
}