C++ qt5学习笔记 2021-3-8(1、访问控件中的子控件,在自建的控件中使用。2、重绘combobox。3、qt中使用opencv,及异常问题的解决。4、qt中配置海康相机。)

44 篇文章 8 订阅

1、访问控件的子控件:

(1)访问控件中的控件:

想要访问控件的控件时,使用下面的两种方法:

QObject::findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
QList QObject::findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

Qt::FindChildOptions options可选可不选,其可选属性有:

Qt::FindDirectChildrenOnly	//值0x0,在object的直接孩子中查找
Qt::FindChildrenRecursively	//值0x1,在object的所有孩子中查找,包括其孩子的孩子
(2)使用时:
  • findchild
//只有一个
QLabel *label1= icon1->findChild<QLabel*>("h1",Qt::FindDirectChildrenOnly);

当未找到名为h1的子控件时,会返回控件本身。如果找到,就会返回这个控件。

qDebug()<<icon1->findChild<QLabel*>("h1",Qt::FindDirectChildrenOnly);

在这里插入图片描述

  • findchildren
QList<QLabel*> qLabels = icon1->findChildren<QLabel*>();
qDebug()<<qLabels;
qDebug()<<qLabels[1];

如果找到,就会返回控件的数组。如果未找到,就会返回一个空的数组。
在这里插入图片描述

(3)在之前的自建控件中使用:

之前写的自建的控件,想要访问其中元素也可以这样来,之前的链接:https://blog.csdn.net/qq_36780295/article/details/113860352

但是试了一下,发现直接查找子元素能找到,但添加子控件的objectname就找不到了,无语,不过也不影响。

当该类型的子控件只有一个时,就用findchild来访问。当该类型的子控件有两个以上的时候,就用findchildren放到容器中,然后通过数组来访问。

查找的代码:
QWidget  *icon1 = icon();
icon1->setParent(ui->label_1);
//只有 1 个label时
QLabel *lab1= icon1->findChild<QLabel*>();
//有 2 个及以上的pushbutton时
QList<QPushButton*> btns = icon1->findChildren<QPushButton*>();

获取到了对象就能对其修改了,如果想要在其他的函数中使用,除了externgolabal,建议还是把实例化和子控件寻址写在头文件中。

数组中的控件顺序是按在内存中的地址来的。new出来的也是从前往后申请内存空间的,所以与自建控件中定义的顺序一致。

控制子元素时:

lab1->setStyleSheet("background-color:red;");  
btns[1]->setStyleSheet("background-color:red;");   //第二个按钮子控件

运行结果:
在这里插入图片描述

2、qss让控件上下左右偏移:

直接方向加像素就可以了:

setStyleSheet("top:2px;left:2px;bottom:2px;right:2px;");

3、重绘combobox的样式:

在这里插入图片描述
combox右边的小三角可以通过drop-down元素来访问,下拉动作则可以通过on来访问。下面给个例子:

ui->oddNumber->setStyleSheet("QComboBox#oddNumber{background-color:white;border-radius:3px;border:0px solid rgb(220,220,220);}"
                             "QComboBox#oddNumber::drop-down{width:15px;height:15px;border-image:url(:/new/prefix1/source/drop_down.png);top:2px;right:1px;}"
                             "QComboBox#oddNumber::drop-down:on{border-image:url(:/new/prefix1/source/drop_up.png);}");

上面图示就是运行结果,下拉时:
在这里插入图片描述

4、添加opencv:

(1)下载opencv:

可以去官网下新版本的,旧版本已经无法下载了。

之前保存过2.4.11版本的:
链接:https://pan.baidu.com/s/1vetQc6TMlgfYahy_djfQ6A
提取码:nm6g

一定要看好自己的qt版本来下载,如果与qt版本不匹配,就会出现缺少dll文件缺失,导致debug模式无法运行。确认版本的两种方法:

  • 通过左下角搜索Qt,比如我查找到的是Qt MSVC2015,就是vs2015版本的qt,那我就要下载有vc14版本的opencv
    在这里插入图片描述

  • 还有一种方法就是打开文件夹到C:\Windows\SysWOW64,翻到一堆msvcpdllmsvcrdll文件的地方,看一下有没有d结尾的dll文件,如:msvcp140d.dll。观察发现只有msvcp140.dll是有对应的带ddll,其他的100110120等都是单独的不带d的。不带d的是release模式会用到的,带d的是debug模式会用到的。所以下载opencv只要下载包含vc14的就行了。如果安装和配置错了opencv版本,qt就找不到debug模式下的dlldebug模式就会出错。

不要想着装其他版本的opencv,然后自己去下debug模式的msvcpmsvcr了,我试过了。下完了放到系统文件夹,还要添加到注册表,各种添加失败浪费时间,最后debug模式还是会由于版本不匹配,找不到自己添加的dll而报错。

opencv下载完提取文件到D盘即可,提取到其他目录,那下面的配置要改一下路径。

(2)配置opencv:

下面以配置opencv-3.4.6msvc2015为例。

环境变量:

我的电脑->属性->高级系统设置->环境变量

在用户变量的PATH中添加:
在这里插入图片描述
地址根据自己提取的opencv路径来,x64中会有多个vc文件夹,配置自己用的那个版本。请不要随便改qt的环境变量,不然可能会导致qtcreater不能用,惨痛的教训。

配置qt:
  • .pro中添加:
# opencv 3.4.6  
INCLUDEPATH += D:\opencv\build\include \
               D:\opencv\build\include\opencv \
               D:\opencv\build\include\opencv2
# 把vc14目录下的所有lib包添加过来,以 d 结尾的是debug模式用的,没有d结尾的是release模式用的
CONFIG(debug,debug|release) {
LIBS += -LD:\opencv\build\x64\vc14\lib \
    -lopencv_world346d
} else {
LIBS += -LD:\opencv\build\x64\vc14\lib \
    -lopencv_world346
}

同样添加自己使用的vc版本。每次修改环境变量或者.pro文件后,运行前都先点击构建->重新构建项目,然后再运行。

  • 在头文件中添加:
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

不一定添加到mainwindow.h中,放到自己建的class的头文件中也可,记得在mainwindow.hinclude这个类。如果添加的头文件下面一堆红线,提示找不到opencv.hpp等,那肯定是.pro文件中的路径写错了,仔细检查检查。还有一种是重新构建时提示无法打开某个刚刚添加的包,多半也是.pro中路径写错了

(3)测试代码:

测试是否可以正常使用时可以修改main.cpp中的代码:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    //QApplication a(argc, argv);
    //MainWindow w;
    //w.showFullScreen();
    //w.show();
    //return a.exec();

    //图片路径自己添加
    Mat img = imread("C:/Users/Administrator/Pictures/qtback/1.jpg");
    imshow("image",img);
    waitKey(0);
    return 0;
}
运行结果:

不出意外的话,会有一个窗口显示图片:
在这里插入图片描述

(4)程序异常结束:

坑我已经踩过了,上面是已经修改好的了,跟着上面的步骤来配置基本不会出错。

测试时:

  • 如果构建时提示某某包不存在,那多半就是.pro中的某个包的包名写错了。

  • 如果配置完以后编译构建,没问题,但是一旦运行就会提示程序异常结束,连个错误原因也没有,一般就是链接库丢失。要看具体是哪个丢失,去到项目文件夹中,找到生成的debug文件夹,在里面找到.exe文件,双击运行,一般就会提示找不到什么什么.dll,在针对着修复。一般可能就是directx缺失,vc++组件缺失,和dll缺失等。directx可以用directx修复工具,dllvc++大多可以在杀毒软件,如腾讯管家的电脑诊所中查找到修复。

  • 如果构建没问题,debugrelease都出现程序异常退出,但是打开项目文件夹,发现exe是能正常运行的,其实表示已经配置好了,重启电脑即可。

其他可能的问题或解决方法:

  • 包的路径写错了,如检查这一段:LIBS += -LD:\opencv\build\x64\vc14\lib \,其中-L和路径中间不要有空格。
  • 检查环境变量有没有配错。再看看是不是以前装过opencv,然后有多个版本的opencv的环境变量。
  • 左下角搜索Qt,打开搜索出来的MSVC,执行set命令,会输出环境变量,再在cmd中执行set,看看两个环境变量是不是一样的,可能有些特殊符号会把环境变量截断,(之前在某篇博客看到的方法,虽然我看了一下没有出错,还是在这里写一下吧,原出处由于重启找不到了,浏览器历史中也找不到,就不放链接了)。
  • release可以,debug就程序异常结束,多半是opencvqtmsvc版本不匹配,如msvc2015就要配置vc14版本的opencv
5、Qt中使用海康相机:
(1)下载海康的sdk软件,我放在网盘里了:

链接:https://pan.baidu.com/s/1VgNfMAMQueJMvaAH88OSgQ
提取码:bv1b

MVS是必须装的,记住安装目录。软件包中的另一个sdk不清楚,最好也装一下。

装完后,将MVS安装目录下的MVS\Development目录下的Include文件夹复制到Qt项目中,再将Libraries文件夹下win64中的MvCameraControl.lib压缩包放到之前拷贝的Include中。
在这里插入图片描述

(2)添加海康sdk到项目:

.pro 中添加代码:

# HKcamera
# $$PWD 表示当前项目地址
LIBS += -L$$PWD/Includes/ -lMvCameraControl
INCLUDEPATH += $$PWD/Includes
DEPENDPATH += $$PWD/Includes

海康相机的函数接口,通过打开mvs软件,帮助->Development,会打开development的文件夹,然后打开Samples->C++Builder->XE5->BasicDemo,在MyCamera中保存了一些接口函数。

把函数接口写到Qt中去,在项目中创建一个Class,名字设为HKcamera

HKcamera.h中添加代码:

#ifndef HKCAMERA_H
#define HKCAMERA_H

//opencv
//#include <QDebug>
//#include <opencv2/opencv.hpp>
//#include <opencv2/core/core.hpp>
//#include <opencv2/highgui/highgui.hpp>
//using namespace cv;

#include "MvCameraControl.h"
#include "MvErrorDefine.h"
#include "CameraParams.h"
#include <string>
#define MY_OK       0
#define MY_FAIL     -1

class HKcamera
{
public:
    HKcamera();
    ~HKcamera();
    static int EnumDevices(MV_CC_DEVICE_INFO_LIST* pstDevList);
    // 打开设备
    int Open(MV_CC_DEVICE_INFO* pstDeviceInfo);
    // 关闭设备
    int Close();
    // 开启抓图
    int StartGrabbing();
    // 停止抓图
    int StopGrabbing();
    // 主动获取一帧图像数据
    int GetOneFrameTimeout(unsigned char* pData, unsigned int* pnDataLen, unsigned int nDataSize, MV_FRAME_OUT_INFO_EX* pFrameInfo, int nMsec);
    // 设置显示窗口句柄
    int Display(void* hWnd);
    // 保存图片
    int SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam);
    // 注册图像数据回调
    int RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser),void* pUser);
    // 注册消息异常回调
    int RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType, void* pUser),void* pUser);
    // 设置和获取Int型参数,如 Width和Height,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    int GetIntValue(IN const char* strKey, OUT unsigned int *pnValue);
    int SetIntValue(IN const char* strKey, IN unsigned int nValue);
    // 设置和获取Float型参数,如 ExposureTime和Gain,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    int GetFloatValue(IN const char* strKey, OUT float *pfValue);
    int SetFloatValue(IN const char* strKey, IN float fValue);
    // 设置和获取Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    int GetEnumValue(IN const char* strKey, OUT unsigned int *pnValue);
    int SetEnumValue(IN const char* strKey, IN unsigned int nValue);
    // 设置和获取Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    int GetBoolValue(IN const char* strKey, OUT bool *pbValue);
    int SetBoolValue(IN const char* strKey, IN bool bValue);
    // 设置和获取String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件UserSetSave
    int GetStringValue(IN const char* strKey, IN OUT char* strValue, IN unsigned int nSize);
    int SetStringValue(IN const char* strKey, IN const char * strValue);
    // 执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    int CommandExecute(IN const char* strKey);
private:
    void*   m_hDevHandle;
};
#endif // HKCAMERA_H

HKcamera.cpp中添加下面代码:

#include "hkcamera.h"

HKcamera::HKcamera()
{
   m_hDevHandle = NULL;
}
HKcamera::~HKcamera()
{
    if (m_hDevHandle)
    {
        MV_CC_DestroyHandle(m_hDevHandle);
        m_hDevHandle    = NULL;
    }
}
//枚举设备
int HKcamera::EnumDevices(MV_CC_DEVICE_INFO_LIST* pstDevList)
{
    int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, pstDevList);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    return MY_OK;
}
//打开设备
int HKcamera::Open(MV_CC_DEVICE_INFO* pstDeviceInfo)
{
    if (NULL == pstDeviceInfo)
    {
        return MY_FAIL;
    }
    int nRet  = MV_CC_CreateHandle(&m_hDevHandle, pstDeviceInfo);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    nRet = MV_CC_OpenDevice(m_hDevHandle);
    if (MV_OK != nRet)
    {
        MV_CC_DestroyHandle(&m_hDevHandle);
        return MY_FAIL;
    }
    return MY_OK;
}
//关闭设备
int  HKcamera::Close()
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    MV_CC_CloseDevice(m_hDevHandle);
    return MV_CC_DestroyHandle(m_hDevHandle);
}
//开启抓图
int  HKcamera::StartGrabbing()
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    return MV_CC_StartGrabbing(m_hDevHandle);
}
//停止抓图
int  HKcamera::StopGrabbing()
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    return MV_CC_StopGrabbing(m_hDevHandle);
}
//主动获取一帧图像数据
int  HKcamera::GetOneFrameTimeout(unsigned char* pData
                                  , unsigned int* pnDataLen
                                  , unsigned int nDataSize
                                  , MV_FRAME_OUT_INFO_EX* pFrameInfo
                                  , int nMsec)
{
    if (NULL == m_hDevHandle || NULL == pData || NULL == pnDataLen || NULL == pFrameInfo)
    {
        return MY_FAIL;
    }
    *pnDataLen  = 0;
    int nRet = MV_CC_GetOneFrameTimeout(m_hDevHandle, pData, nDataSize, pFrameInfo, nMsec);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    *pnDataLen = pFrameInfo->nFrameLen;
    return MY_OK;
}
//显示
int  HKcamera::Display(void* hWnd)
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    return MV_CC_Display(m_hDevHandle, hWnd);
}
//保存图片
int  HKcamera::SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam)
{
    if (NULL == pstParam)
    {
        return MY_FAIL;
    }
    return MV_CC_SaveImageEx(pstParam);
}
//注册图像数据回调
int  HKcamera::RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char * pData
                                                               ,MV_FRAME_OUT_INFO_EX* pFrameInfo
                                                               ,void* pUser)
                                     ,void* pUser)
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    return MV_CC_RegisterImageCallBackEx(m_hDevHandle, cbOutput, pUser);
}
//注册消息异常回调
int  HKcamera::RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType
                                                                      ,void* pUser)
                                         ,void* pUser)
{
    if (NULL == m_hDevHandle)
    {
        return MY_FAIL;
    }
    return MV_CC_RegisterExceptionCallBack(m_hDevHandle, cbException, pUser);
}
//获取和设置Int型参数,如 Width和Height,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
int  HKcamera::GetIntValue(IN const char* strKey, OUT unsigned int *pnValue)
{
    if (NULL == m_hDevHandle || NULL == strKey || NULL == pnValue)
    {
        return MY_FAIL;
    }
    MVCC_INTVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_INTVALUE));
    int nRet = MV_CC_GetIntValue(m_hDevHandle, strKey, &stParam);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    *pnValue = stParam.nCurValue;
    return MY_OK;
}
int  HKcamera::SetIntValue(IN const char* strKey, IN unsigned int nValue)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetIntValue(m_hDevHandle, strKey, nValue);
}
//获取和设置Float型参数,如 ExposureTime和Gain,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
int  HKcamera::GetFloatValue(IN const char* strKey, OUT float *pfValue)
{
    if (NULL == m_hDevHandle || NULL == strKey || NULL == pfValue)
    {
        return MY_FAIL;
    }
    MVCC_FLOATVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_FLOATVALUE));
    int nRet = MV_CC_GetFloatValue(m_hDevHandle, strKey, &stParam);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    *pfValue = stParam.fCurValue;
    return MY_OK;
}
int  HKcamera::SetFloatValue(IN const char* strKey, IN float fValue)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetFloatValue(m_hDevHandle, strKey, fValue);
}
//获取和设置Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
int  HKcamera::GetEnumValue(IN const char* strKey, OUT unsigned int *pnValue)
{
    if (NULL == m_hDevHandle || NULL == strKey || NULL == pnValue)
    {
        return MY_FAIL;
    }
    MVCC_ENUMVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_ENUMVALUE));
    int nRet = MV_CC_GetEnumValue(m_hDevHandle, strKey, &stParam);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    *pnValue = stParam.nCurValue;
    return MY_OK;
}
int  HKcamera::SetEnumValue(IN const char* strKey, IN unsigned int nValue)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetEnumValue(m_hDevHandle, strKey, nValue);
}
//获取和设置Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
int  HKcamera::GetBoolValue(IN const char* strKey, OUT bool *pbValue)
{
    if (NULL == m_hDevHandle || NULL == strKey || NULL == pbValue)
    {
        return MY_FAIL;
    }
    int nRet = MV_CC_GetBoolValue(m_hDevHandle, strKey, pbValue);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    return MY_OK;
}
int  HKcamera::SetBoolValue(IN const char* strKey, IN bool bValue)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetBoolValue(m_hDevHandle, strKey, bValue);
}
//获取和设置String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件UserSetSave
int  HKcamera::GetStringValue(IN const char* strKey
                              , IN OUT char* strValue
                              , IN unsigned int nSize)
{
    if (NULL == m_hDevHandle || NULL == strKey || NULL == strValue)
    {
        return MY_FAIL;
    }
    MVCC_STRINGVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_STRINGVALUE));
    int nRet = MV_CC_GetStringValue(m_hDevHandle, strKey, &stParam);
    if (MV_OK != nRet)
    {
        return MY_FAIL;
    }
    strcpy_s(strValue, nSize, stParam.chCurValue);
    return MY_OK;
}
int  HKcamera::SetStringValue(IN const char* strKey, IN const char* strValue)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetStringValue(m_hDevHandle, strKey, strValue);
}
//执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
int  HKcamera::CommandExecute(IN const char* strKey)
{
    if (NULL == m_hDevHandle || NULL == strKey)
    {
        return MY_FAIL;
    }
    return MV_CC_SetCommandValue(m_hDevHandle, strKey);
}

使用时,在mainwindow.h中引入hkcamera 类,创建海康相机的对象就能使用了。

同目录下的BasicDemo是演示的实例,上面这些函数接口的使用可以参考这里。

为了在C++中使用海康相机,需要使用代码执行以下操作:

1、回调函数。
这个函数每一次回调,就会执行一次,在回调函数中 使用 MV_FRAME_OUT_INFO_EX 接收相机图像信息。

2EnumDevices()  OpenDevice() 枚举和打开设备。

3MV_CC_RegisterImageCallBackEx()  注册回调函数

4SetTriggerMode()   设置触发模式
触发模式即指定怎样触发拍一张或多张照,包括软触发和硬触发,软触发可以是一个commond,硬触发则可以是一个电信号
除此之外,还可以通过SetTriggerMode(MV_TRIGGER_MODE_OFF);来关闭触发模式,这样开始采集流后就会一直触发,而非指定次数,或发送信号的触发

5、数据包延迟,像素通道,Gamma等属性。

6MV_CC_StartGrabbing()  获取流,如果以上一些操作都设置好了,打开获取流以后,相机就会进入画面捕捉了
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值