- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
一段时间以来,我一直在使用 Qt 开发一个应用程序,在该应用程序中我必须从相机中抓取帧。相机将在与应用程序其余部分不同的线程中运行。我遵循了以下建议:
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
和
https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
不要子类化 QThread。相反,我创建了一个工作对象 CCameraCapture 并将其移动到 QThread。相机的帧抓取由连接到抓取帧槽的 QTimer 控制。将 CCameraCapture 移动到 QThread 后,可以通过启动计时器来开始捕获。我的问题是:我必须调用 QThread 类的 start() 吗?我的方法无需调用即可工作。循环由定时器执行,worker 实际上在另一个线程中工作,而没有调用 start。所以我想知道如果使用定时器,调用 start() 是否有意义?为了清楚起见,我将我的 Worker 类放在下面,它是在主应用程序中创建的:
m_CameraCaptureThread= new QThread();
m_CameraCapture = new CCameraCapture(30);
m_CameraCapture->moveToThread(m_CameraCaptureThread);
//Connect error signal
QObject::connect(m_CameraCapture, SIGNAL(error(QString,QString)), this, SLOT(reportError(QString,QString)));
//Connect started() of QThread to the starting function of the worker class
connect(m_CameraCaptureThread, SIGNAL(started()), m_CameraCapture, SLOT(startGrabbing()));
//Connect the finished signal of the worker class to the thread for quitting the loop
connect(m_CameraCapture, SIGNAL(finished()), m_CameraCaptureThread, SLOT(quit()));
//This connections guarantees that the *m_CVideoCapture is automatically deleted if the event loop of the thread is terminated. Therefore, m_CVideoCapture does not need to be released manually if the capturing process is stopped.
QObject::connect(m_CameraCaptureThread, SIGNAL(finished()), m_CameraCaptureThread, SLOT(deleteLater()));
QObject::connect(m_CameraCapture, SIGNAL(finished()), m_CameraCapture, SLOT(deleteLater()));
//Connect sendFrame to update frame for displaying the current frame
QObject::connect(m_CameraCapture, SIGNAL(sendFrame(QImage)), this, SLOT(receiveFrame(QImage)));
/**
所以到目前为止,还没有调用 m_CameraCaptureThread->start() 来启动处理循环。但是如果我调用 CameraCapture->startGrabbing() 它会很好地工作。 grabFrame() 槽由计时器触发,帧被发送到主应用程序。然而,到目前为止我看到的所有代码示例都调用了 start(),即使它们使用了计时器:例如: http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/ (用法2-1在页尾)
这是我的 CCameraCapture.h:
/**
@file CCameraCapture.h
@brief this file contains the definition of the class CCameraCapture.
**/
#ifndef CCameraCapture_H
#define CCameraCapture_H
//Required Qt libs
#include <QObject>
#include <QImage>
#include <QTimer>
#include <QString>
#include <QMutex>
#include <QDebug>
//Required OpenCV libs
#include <opencv2\opencv.hpp>
/**
@class CCameraCapture
@brief This class defines a video capture object which should be moved to thread.
class CCameraCapture : public QObject{
Q_OBJECT
public:
/**
@brief Constructor of CCameraCapture.
@param frameRate Desired frame rate (if possible)
*/
CCameraCapture(double frameRate=30);
/**
@brief Destructor of CCameraCapture.
*/
~CCameraCapture();
/**
@brief This function terminates the thread.
*/
void exitThread();
bool startGrabbing();
void stopGrabbing();
/**
@brief Check if camera is running
@return Returns true if camera is running
*/
bool isGrabbing();
private:
//The openCV capturing object to access the camera
cv::VideoCapture m_Cap;
// Device index
int m_IdxDevice;
// Timer for triggring grab frame
QTimer m_Timer;
//The most recent frame
QImage m_Frame;
//Mutex to lock variables
QMutex m_Mutex;
private slots:
/**
@brief This slot grabs a frame from the camera. It is triggered by the timer m_Timer.
*/
void grabFrame();
signals:
/**
@brief This signal needs to be connected to the slot in the main application which should receive the images.
@param img The most recent frame.
*/
void sendFrame(QImage currentFrame);
/**
@brief This signal is emitted if an error occurs
@param errMsg QString contains the error message to be displayed.
@param errTitle QString contains the title of the diplayed error message.
This signal should be connected to a slot in the main application. It allows to send error reports back to the main application which can be displayed on screen
*/
void error(QString errMsg,QString errTitle);
void finished();
};
#endif //CCameraCapture_H
这是cpp文件:
/**
@file CCameraCapture.cpp
@brief this file contains the function definitions of CCameraCapture.
**/
#include "CCameraCapture.h"
CCameraCapture::CCameraCapture(double frameRate):m_Mutex(),m_IdxDevice(0)
{
//Connect timer to grabFrame
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(grabFrame()), Qt::DirectConnection);
//Set framerate
m_Timer.setInterval(1000/frameRate);
}
CCameraCapture::~CCameraCapture(void)
{
}
void CCameraCapture::grabFrame(){
qDebug() << "Worker thread ID" << this->thread();
//Lock this function
QMutexLocker ml(&m_Mutex);
//Local image storage
cv::Mat cvFrameBGR,cvFrameRGB;
//Get new frame from camera
m_Cap>>cvFrameBGR;
//Convert frame to RGB
cv::cvtColor(cvFrameBGR, cvFrameRGB, CV_BGR2RGB);
//Convert cv::Mat to QImage
QImage m_Frame=QImage((uchar*)(cvFrameRGB.data),cvFrameRGB.cols,cvFrameRGB.rows,QImage::Format_RGB888);
//Send frame to receivers
emit sendFrame(m_Frame);
}
bool CCameraCapture::startGrabbing(){
//Lock this function
QMutexLocker ml(&m_Mutex);
//Check if camera is open
if(!m_Cap.isOpened()){
//Connect to camera
if(!m_Cap.open(m_IdxDevice)){
emit error(QString("Could not connect to Camera."),QString("Error: No camera detected"));
return 0;
}
else{
//Start grabbing
m_Timer.start();
return 1;
}
}
else{
//Start grabbing
m_Timer.start();
return 1;
}
}
void CCameraCapture::stopGrabbing(){
//Lock this function
QMutexLocker ml(&m_Mutex);
//Stop grabbing
m_Timer.stop();
}
bool CCameraCapture::isGrabbing(){
//Lock this function
QMutexLocker ml(&m_Mutex);
//Return true if timer is running and triggering grabFrame
return m_Timer.isActive();
}
void CCameraCapture::exitThread(){
//Lock this function
QMutexLocker ml(&m_Mutex);
//Stop grabbing
stopGrabbing();
//Release camera
m_Cap.release();
//Emit finished signal which should be connected to quit() of QThread and deleteLater() of this class;
emit finished();
}
最佳答案
如果没有调用 start,我怀疑它没有在新线程上运行。
虽然您可能不需要事件循环(尽管 QTimer 需要),但 Qt documentation状态:-
Begins execution of the thread by calling run(). The operating system will schedule the thread according to the priority parameter. If the thread is already running, this function does nothing.
因此,您应该调用 start,但如果它已经在运行,那么再次调用它也没有什么坏处。
您可以通过在将对象移动到新线程之前和之后调用 QObject 的 thread() 函数并比较返回的指针来测试该对象在哪个线程上运行。
关于c++ - 在不调用 QThread::start() 的情况下使用 QThread 是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22659131/
我有一张 table People (First_Name, Last_Name)。此表包含与示例中一样重复的记录(并非所有行都重复): First_Name Last_Name John
我用 Java 编写过很多程序,之前也涉足过 C++。我在各种 C++ 书籍中阅读了有关指针的内容,并完成了书籍中的各种示例。 我了解指针的基础知识,但有一件事我一直不清楚。指针在现实世界中的应用是什
线 .Mappings(m => m.FluentMappings.AddFromAssemblyOf() 它有什么作用?它会在派生自 ClassMap 的 Product 类的程序集中查找任
我有用于打印数字的自定义打印功能。我制作了一个 ASCII 版本和一个 UTF-16LE 版本。 UTF-16LE 版本对 0-9 使用全角代码/字符,对十六进制使用 A-F。在调试我的函数时,我注意
这是我的代码片段: float ab(float); 以后 if(ab(temp)
我在一个项目文件中包含以下代码: //begin of the file ((window) => { 'use strict'; class View extends GSM.Event
我一直在到处寻找关于 ? 用法的正确解释。和 *。我注意到我可以使用以下方法拒绝所有用户的访问: 如果我想允许某个组,我应该在其上方添加下一行: 但是当我看到人们使用 ? 时,我开始忘记什么意思,
我正在关注 melon js tutorial .这是在我的 HUD.js 文件的顶部。 game.HUD = game.HUD || {} 我以前在其他例子中见过这个。 namespace.some
我正在处理一个包含数千行代码的文件。我正在第 700 行实现一个算法。我经常不得不离开这些行来检查文件中的其他方法。 导航回到我实际编码的地方通常很痛苦。如果我可以在第 700 行设置一个航路点并为其
我遇到了这段代码 do { if (higherQuality && w > targetWidth) { w /= 2; if (w &
uint8_t * const LCDMem = (uint8_t *) &LCDM3; 此代码在 msp430fg4618 培训套件中用于 lcd 配置。谁能解释一下上述代码的含义? 它允许使用 a
上下文 阅读一些内核代码。 问题 我不明白这行是什么意思 *(void **) &(int[2]){0,PAGE_SIZE}; 还有更多,这是什么意思 {0,PAGE_SIZE} 对我来说,它看起来不
我正在查看 Underscore.js 的源代码库,专门用于 map方法(该页面第 85 行左右,并复制到此处): _.map = function(obj, iterator, context)
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
我是一名优秀的程序员,十分优秀!