MainWindow的Worker线程的QT更新变量
QT Update variable of worker thread from mainwindow
我正在使用QT多线程概念显示OpenCV视频
我还希望更新按钮单击的私有"路径"变量。所以我添加了
connect(this, SIGNAL(send_to_worker(QString)),workers[view], SLOT(get_from_main(QString)));
但是,get_from_main(qString(函数永远不会被调用。
我可以知道从MainWindow更新Worker线程类变量的最安全方法是什么?
这是完整的代码..
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QString path, int id);
~Worker();
public slots:
void readVideo(QString path = "");
void get_from_main(QString path);
signals:
// frame and index of label which frame will be displayed
void frameFinished(cv::Mat frame, int index);
void finished(int index);
private:
QString filepath;
int index;
};
//worker.cpp
#include "worker.h"
#include <QDebug>
#include <QThread>
#include <QTime>
Worker::Worker(QString path, int id) : filepath(path), index(id)
{
}
Worker::~Worker()
{
}
void Worker::get_from_main(QString path)
{
qDebug() << "updating";
}
void Worker::readVideo(QString path)
{
if (path.length() > 0)
filepath = path;
cv::VideoCapture cap(filepath.toStdString());
if (! cap.isOpened())
{
qDebug() << "Can't open video file " << filepath;
emit finished(index);
return;
}
cv::Mat frame;
while (true)
{
cap >> frame;
if (frame.empty())
{
frame = cv::Mat(cv::Size(720, 576), CV_8UC3, cv::Scalar(192, 0, 0));
emit frameFinished(frame, index);
break;
}
emit frameFinished(frame.clone(), index);
QThread::msleep(30);
}
emit finished(index);
}
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <opencv2/opencv.hpp>
#include "worker.h"
#define MAX_NUM_CAM 8
namespace Ui {
class MainWindow;
}
class QThread;
class QLabel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void init();
private slots:
void displayFrame(cv::Mat frame, int index);
void file_open_clicked();
signals:
send_to_worker(QString path);
private:
Ui::MainWindow *ui;
int numCams;
QLabel *labels[MAX_NUM_CAM];
QThread* threads[MAX_NUM_CAM];
Worker* workers[MAX_NUM_CAM];
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>
#include <QLabel>
#include <QGridLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qRegisterMetaType< cv::Mat >("cv::Mat");
qDebug() << "Main thread " << QThread::currentThreadId();
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
QGridLayout *grid = new QGridLayout;
int numCols = 2;
numCams = 4;
int row = 0, col = 0;
for (int i = 0; i < numCams; i++)
{
labels[i] = new QLabel;
row = i / numCols;
col = i % numCols;
grid->addWidget(labels[i], row, col);
threads[i] = new QThread;
workers[i] = new Worker(QString("/home/shang/Videos/%1.mp4").arg(i+1), i);
workers[i]->moveToThread(threads[i]);
connect(workers[i], SIGNAL(frameFinished(cv::Mat, int)), this, SLOT(displayFrame(cv::Mat,int)));
connect(threads[i], SIGNAL(started()), workers[i], SLOT(readVideo()));
connect(workers[i], SIGNAL(finished(int)), threads[i], SLOT(quit()));
connect(workers[i], SIGNAL(finished(int)), workers[i], SLOT(deleteLater()));
connect(threads[i], SIGNAL(finished()), threads[i], SLOT(deleteLater()));
threads[i]->start();
}
this->centralWidget()->setLayout(grid);
}
void MainWindow::file_open_clicked(){
QString Path = QFileDialog::getSaveFileName( this,tr("OpenVideo"),"","Video (*.avi)");
if(Path.isEmpty())
return;
view =3;
connect(this, SIGNAL(send_to_worker(QString)),workers[view], SLOT(get_from_main(QString)));
emit this->send_to_worker(recorder_Path);
}
void MainWindow::displayFrame(cv::Mat frame, int index)
{
QPixmap p = QPixmap::fromImage(QImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888).rgbSwapped());
p = p.scaled(QSize(frame.cols/2, frame.rows/2));
labels[index]->setPixmap(p);
}
QT OpenCV使用STD播放视频:: thread
您正在尝试定期执行操作,同时仍在处理事件 - 这只是呼吁QTimer
。
(请注意未经测试的代码。(
更改您的Worker
类以使用QTimer
而不是阻止事件队列的循环...
class Worker: public QObject {
Q_OBJECT;
public:
Worker (QString path, int id);
~Worker();
public slots:
void readVideo(QString path = "");
void get_from_main(QString path);
signals:
// frame and index of label which frame will be displayed
void frameFinished(cv::Mat frame, int index);
void finished(int index);
private:
QString filepath;
int index;
QTimer timer;
cv::VideoCapture cap;
};
Worker::Worker (QString path, int id)
: filepath(path)
, index(id)
, timer(this)
, cap(filepath.toStdString())
{
/*
* Connect QTimer::timeout to the readVideo slot that will read a
* single frame on each signal at 30ms intervals.
*/
connect(&timer, &QTimer::timeout, this, &Worker::readVideo);
timer.start(30);
}
Worker::~Worker ()
{
}
void Worker::get_from_main (QString path)
{
qDebug() << "updating";
filepath = path;
cap = cv::VideoCapture(filepath);
if (!cap.isOpened()) {
qDebug() << "Can't open video file " << filepath;
emit finished(index);
}
}
void Worker::readVideo ()
{
cv::Mat frame;
cap >> frame;
if (frame.empty())
{
frame = cv::Mat(cv::Size(720, 576), CV_8UC3, cv::Scalar(192, 0, 0));
emit frameFinished(frame, index);
break;
}
emit frameFinished(frame.clone(), index);
}
现在Worker::readVideo
只需从捕获中读取单个帧,然后返回事件循环。
还删除线...
connect(threads[i], SIGNAL(started()), workers[i], SLOT(readVideo()));
来自MainWindow::init
。正如我上面所述,这是未经测试的,可能需要 lot 更多错误检查。但这应该给您一个好主意。
相关文章:
- cmake更新缓存的变量
- 为什么我的变量没有更新,我的 LED 没有亮起?
- 用非原子更新原子变量,反之亦然
- 字符串变量未更新 c++
- C++ 和 Boost.Python - 如何将变量公开给 python 并在循环中更新它?
- 为什么数组变量正在更新
- 为什么 beginthreadex 线程参数变量在父线程中没有更新
- 互斥体和变量更新
- 在 for 循环中更新两个变量时遇到问题C++
- 在这种情况下,当尝试从单独的类更新变量时,我是否需要使用指针?
- 如何使用 if 语句 MQL5 更新变量
- MainWindow的Worker线程的QT更新变量
- 我将如何连续更新变量,并同时等待输入
- 在条件上更新变量的最快方法是什么?
- MSVC2015更新3变量模板解决方法
- 如何有条件地同时多线程和更新变量
- 函数在执行while循环时不更新变量
- 从perl更新c++变量
- 指向变量的指针在解引用时没有更新变量
- 无法让它更新变量C++