求助大神!!QT通过信号和槽传递照图像指针,无法在label上显示

weixin_53157219 2021-02-01 09:03:45
void Widget::showImage(QImage *image)
{
ui->label_show->setScaledContents(true);
ui->label_show->setPixmap(QPixmap::fromImage(*image));
}

上面是槽函数,通过传递过来的信号进行UI显示,如果把上面两个都注释运行没有问题,可是一但开启就卡死,

下面是代码:

主函数.h文件
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>
#include <QImage>
#include "MvCameraControl.h"
#include "camthread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

signals:
void needDeviceListSignal();//发送信号获取设备列表
void needGrabImage(int Id,MV_CC_DEVICE_INFO_LIST list);

private slots:
void getDeviceList(QString *text,MV_CC_DEVICE_INFO_LIST list);//获取设备列表并显示
void showImage(QImage *image);//显示图片槽函数

private slots:
void on_pushButton_seachDevice_clicked();
void on_pushButton_grabImage_clicked();

private:
QThread *thread;
CamThread *cam1;
MV_CC_DEVICE_INFO_LIST stDeviceList;//设备列表全局函数

private:
Ui::Widget *ui;
};
#endif // WIDGET_H


.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMetaType>


Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
qRegisterMetaType<MV_CC_DEVICE_INFO_LIST>("MV_CC_DEVICE_INFO_LIST");

/* * 初始化对象* */
cam1 = new CamThread();
thread = new QThread(this);
cam1->moveToThread(thread);

/* * 信号槽 * */
connect(this,&Widget::needDeviceListSignal,cam1,&CamThread::EnumDevice);//调用线程查询设备列表
connect(cam1,&CamThread::sendDeviceListSignal,this,&Widget::getDeviceList,Qt::DirectConnection);//根据线程查询列表返回信息调用显示槽函数
connect(this,&Widget::needGrabImage,cam1,&CamThread::connectDevice);//调用连接设备及取图函数
connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage);//通过传递回的信号调用图像显示函数
}

Widget::~Widget()
{
delete ui;
cam1->isOpen = false;
thread->quit();
thread->wait();
}

void Widget::getDeviceList(QString *text,MV_CC_DEVICE_INFO_LIST list)
{
stDeviceList = list;
ui->comboBox_DeviceList->addItem(*text);
}

void Widget::showImage(QImage *image)
{
ui->label_show->setScaledContents(true);
ui->label_show->setPixmap(QPixmap::fromImage(*image));
}

void Widget::on_pushButton_seachDevice_clicked()//按下查询设备列表按钮
{
thread->start();
emit needDeviceListSignal();
qDebug()<< "发送查询信号";
}

void Widget::on_pushButton_grabImage_clicked()//按下采集按钮
{
int Id = ui->comboBox_DeviceList->currentIndex();
emit needGrabImage(Id,stDeviceList);
}


下面是线程中发送信号的部分
void CamThread::GetImage(void *handle,MV_FRAME_OUT_INFO_EX stImageInfo,unsigned char * pData)//循环取图
{

while (isOpen)
{
int nRet = MV_CC_GetOneFrameTimeout(handle, pData, g_nPayloadSize, &stImageInfo, 100);
if (nRet == MV_OK)
{
cv::Mat dstImga;
dstImga = Convert2Mat(&stImageInfo, pData);
//cv::imshow("image",dstImga);
cv::cvtColor(dstImga,dstImga,cv::COLOR_BGR2RGB);
QImage Qtemp = QImage((const unsigned char*)(dstImga.data), dstImga.cols, dstImga.rows, dstImga.step, QImage::Format_RGB888);
emit sendImageSignal(&Qtemp);
}
else
{
QString text = QString("无图像数据!nRet [%1]").arg(nRet);
qDebug() << text;
free(pData);
pData = NULL;
return;
}
//qDebug()<< "循环取图";
QThread::msleep(500);
qDebug()<<"子线程"<<QThread::currentThread();
}
}
...全文
919 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
熊猫呀 2021-02-03
  • 打赏
  • 举报
回复
引用 5 楼 weixin_53157219 的回复:
我咋感觉是这个有点问题呢 QImage Qtemp = QImage((const unsigned char*)(dstImga.data), dstImga.cols, dstImga.rows, dstImga.step, QImage::Format_RGB888); emit sendImageSignal(&Qtemp); Qtemp 这个传递信号后 如果是默认的AutoConnet 他应该会放到队列循环中。然后 Qtemp 应该会消失,你把这个 Qimage 变成 指针试试
不是这个的问题 像3楼说的一样 就是没有采样直连,导致信号在队列等待连接,结果连接上的时候原地址改变了,所有导致野指针,报错了,报的是跟什么c盘sougou文件的问题一样,网上查的资料都说这个就是野指针造成的[/quote] QImage Qtemp 在栈上 当你发出信号以后 AutoConnet 连接 就会把 Qtemp 的栈地址 扔到消息队列中,然后程序继续执行。Qtemp生命周期结束。所以然你autoConnet 时用个指针 new 。这不跟 windows 的postmessage 和 sendmessage 一样的嘛?
  • 打赏
  • 举报
回复
直连就直接在执行的时候跑到槽函数里,图片指针指向的数据还在 如果是多线程会自适应成队列方式,就是先把信号和参数缓存,扔事件循环里,等事件循环的下一轮来了再执行,这时候图片指针在原线程可能已经释放或者改变地址了。 多线程也可以开一个buffer然后用阻塞队列的连接方式,这样不会导致崩溃。
熊猫呀 2021-02-02
  • 打赏
  • 举报
回复
引用 1 楼 weixin_53157219 的回复:
随便试了试 原来是connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage);//通过传递回的信号调用图像显示函数 通过信号传递回来的图片要显示必须使用最后一个参数,调整为connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage,Qt::DirectConnection); 这样就可以了 希望对同样遇到此问题的人一点帮助
我咋感觉是这个有点问题呢 QImage Qtemp = QImage((const unsigned char*)(dstImga.data), dstImga.cols, dstImga.rows, dstImga.step, QImage::Format_RGB888); emit sendImageSignal(&Qtemp); Qtemp 这个传递信号后 如果是默认的AutoConnet 他应该会放到队列循环中。然后 Qtemp 应该会消失,你把这个 Qimage 变成 指针试试
weixin_53157219 2021-02-02
  • 打赏
  • 举报
回复
我咋感觉是这个有点问题呢 QImage Qtemp = QImage((const unsigned char*)(dstImga.data), dstImga.cols, dstImga.rows, dstImga.step, QImage::Format_RGB888); emit sendImageSignal(&Qtemp); Qtemp 这个传递信号后 如果是默认的AutoConnet 他应该会放到队列循环中。然后 Qtemp 应该会消失,你把这个 Qimage 变成 指针试试 [/quote] 不是这个的问题 像3楼说的一样 就是没有采样直连,导致信号在队列等待连接,结果连接上的时候原地址改变了,所有导致野指针,报错了,报的是跟什么c盘sougou文件的问题一样,网上查的资料都说这个就是野指针造成的
weixin_53157219 2021-02-02
  • 打赏
  • 举报
回复
引用 1 楼 weixin_53157219 的回复:
随便试了试 原来是connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage);//通过传递回的信号调用图像显示函数 通过信号传递回来的图片要显示必须使用最后一个参数,调整为connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage,Qt::DirectConnection); 这样就可以了 希望对同样遇到此问题的人一点帮助
引用 3 楼 这是一个正经昵称 的回复:
直连就直接在执行的时候跑到槽函数里,图片指针指向的数据还在 如果是多线程会自适应成队列方式,就是先把信号和参数缓存,扔事件循环里,等事件循环的下一轮来了再执行,这时候图片指针在原线程可能已经释放或者改变地址了。 多线程也可以开一个buffer然后用阻塞队列的连接方式,这样不会导致崩溃。
是的 我看了看海康的事例代码,里面就做了一个用作缓存的buffer,这样就不会在出现类似野指针的报错了
weixin_53157219 2021-02-01
  • 打赏
  • 举报
回复
随便试了试 原来是connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage);//通过传递回的信号调用图像显示函数 通过信号传递回来的图片要显示必须使用最后一个参数,调整为connect(cam1,&CamThread::sendImageSignal,this,&Widget::showImage,Qt::DirectConnection); 这样就可以了 希望对同样遇到此问题的人一点帮助
池皓辰 2022-04-12
  • 举报
回复
@weixin_53157219 我那个是在槽函数里用label直接显示不了图,自己电脑里的图也显示不了,放在槽函数外面就可以显示,你知道为什么吗?

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧