在两个不同线程之间的信号/槽调用后损坏QImage
Corrupt QImage after a signal/slot call between two different threads
我通过信号/插槽机制发送一个QImage,在两个线程之间(后台DB线程和GUI线程)。GUI插槽接收损坏的图像(一些像素随机损坏)。我已经这样做了,从来没有任何问题。会出什么问题呢?
程序太复杂,不能在这里包括,但这里有一些相关的信息:
- 发送线程(DB)是一个常规的QThread,带有事件循环,运行DataBaseInterface QObject类,该类被移动到该线程
- 信号/槽连接在moveToThread之后完成,所以每个对象都在它的最后一个线程中。这意味着显式地使用QueuedConnection没有什么区别,因为这已经是情况了。
-
QImage不是直接在信号/槽参数中发送的,而是在包含其他东西(三个qvector)的结构体中发送的。这个结构体是用:
注册的qRegisterMetaType<MyStruct>("MyStruct");
-
QImage不是使用外部缓冲区创建的,而是使用(width, height, Format)构造函数创建的。因此,图像缓冲区是内部维护的,因此隐式共享
- 如果我在发出信号后将图像保存到DB线程中的磁盘,这很好。如果我把它保存在槽的开始,它是损坏的。
任何想法?
谢谢!
Ok,为了使图像不损坏,您应该确保以下内容:每个包含正在发送的结构的数据必须具有复制构造函数,避免发送数据指针,如果您这样做,则确保这些数据驻留在内存堆中,这些情况下的连接类型是Qt::QueuedConnection,在建立图像上的标签您认为应该配置如下:
label->setBackgroundRole(QPalette::Base);
label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
label->setScaledContents(true);
图像或结构的插槽应该看起来像这样,在我的opencv和QT的情况下是:
void interfaz::actImagenFromVideo(cv::Mat myImage)
{
QImage image(myImage.data,myImage.cols, myImage.rows, myImage.step, QImage::Format_RGB888 );
label->setPixmap(QPixmap::fromImage(image.rgbSwapped()));
}
你的QThread的运行函数应该看起来像这样:
void THREAD::run()
{
while(true){
{
QMutexLocker locker(&mutex);
if (stopped) {
stopped = false;
break;
}
}
cap>>videoIn;
emit image_ready(videoIn.clone()); //the use of cv::Mat::clone() is very important in openCV
}
}
相关文章:
- Qt信号和插槽如果从QRunnable或其他线程调用,则不起作用
- QNetworkReply::done() 信号是按顺序调用还是同时调用?
- 当再次触发信号时,从Qt插槽执行的功能被第二次调用时会发生什么?
- C++发出信号稍后在 QML 中调用
- 从 Qt 中的信号调用成员函数的问题
- 当对话框中的任何小部件发出信号时,是否可以调用插槽
- 这是在Qt信号和插槽中使用参数调用函数的好方法吗?
- 从第二个线程调用Qt信号有效 - >对连接的插槽没有影响
- 如何使用unique_ptr声明调用构造函数并处理程序终止信号
- 如何使 WaitForSingleObject 在从 main 调用的线程内接收信号作为类成员函数
- 无法从抽象类调用按钮信号
- 如果不同的线程调用另一个不同线程的相同信号,则需要静音
- 当 epoll 发出活动信号时,recv() 调用怎么会阻塞
- Qt connect(*发送器,*信号,*接收器,*方法)不调用插槽
- 在调用stop()之后,将发送qTimer超时信号
- 程序在调用类指针时收到信号SIGSEGV,分段错误
- Qt UI 插槽不是由从基类继承的信号调用的
- 如何从插槽中找出哪个信号调用了此插槽
- 从Boost signals2信号调用的函子的成员变量不更新
- 是否存在串行化boost::signals2信号调用的现有方法