我必须编写一个应用程序,在一个 Widget 中显示加载的视频,拉帧,转换它们,然后将它们放入另一个 Widget,最好是 QGraphicsView,并希望同步。同步它们非常重要。
我写了一个测试线程,主要内容是这样的:
void HSV::display() {
Ui::MainWindow ui; //1
int j=0;
QTimer *timer = new QTimer;
for(int i=1; i<4; i++){
QString numer = QString::number(i);
QImage imageTest(numer+".jpg");
QGraphicsPixmapItem* test = new QGraphicsPixmapItem(QPixmap::fromImage(imageTest));
QGraphicsScene* sceneHSV = new QGraphicsScene;
sceneHSV->addItem(test);
//2
ui.graphicsViewKalibracjaHSV->setScene(sceneHSV);
ui.graphicsViewKalibracjaHSV->fitInView(sceneHSV->sceneRect(),Qt::KeepAspectRatio);
ui.graphicsViewKalibracjaHSV->show();
timer->start(500);
if(i==3) {
i=1;
}
j++;
if (j>40) {
break;
}
}
}
这不是我需要的,但它只是一个测试。如果我把文字放在那里,它会很好地显示,继续显示。但是这些图像......当到达第一条 ui 行(//2 )时立即崩溃。我毫不怀疑这种做事方式真的很糟糕。
如果我删除位于//1 的 Ui::MainWindow ui;
,它会告诉我 ui 未在此范围内声明
。
所以我的问题是,如何从单独的线程访问和修改主窗口中的 ui 元素?
编辑: 好的,一个更实际的想法。我将简单地将视频文件 URL 从 GUI 线程传递到工作线程,在那里执行所有操作并传回 2 个处理过的图像(对于每个视频帧),每个 QGraphicsView 一个。一张是正常的,有标记点,一张是变形的。我现在知道如何将内容从工作线程传递到 GUI 线程,但是如何将 QString 从 GUI 传递到工作线程,以及如何接收它?
最佳答案
简短的回答:你不能。
Qt 帮助:线程基础:
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.
你可以做什么:你可以在主线程中使用 ui,通过信号/槽系统将 QImage
(或其他与 ui 无关的数据)传递到单独的线程,在那里处理它并传递它回来了。
更新(我该怎么做?我的意思是,在线程之间来回传递 QImage 并同时连续显示两个视频?– Petersaber)
我不是视频专家,但我可以给你提示。假设您有一个 Widget
,它接受 QImage
并且必须显示它。 Processor
是一个对象,它处理图像并将其返回给 gui 线程。 Processor
应该派生自 QObject
。
Widget.h
class Widget : public QWidget, private Ui::Widget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
void enqueueImage(const QImage &img);
signals:
void process(const QImage &img);
private:
void showNextImage();
private slots:
void onProcessed(const QImage &img);
private:
QThread *mThread;
QScopedPointer < Processor > mProcessor;
QList < QImage > mImagesPool;
};
Widget.cpp
Widget::Widget(QWidget *parent) :
QWidget(parent)
, mThread(new QThread(this))
, mProcessor(new Processor)
{
setupUi(this);
mProcessor->moveToThread(mThread);
connect(this, SIGNAL(process(QImage)), mProcessor, SLOT(process(QImage)));
connect(mProcessor, SIGNAL(processed(QImage)), SLOT(onProcessed(QImage)));
}
void Widget::enqueueImage(const QImage &img)
{
mImagesPool.append(img);
showNextImage();
}
void Widget::showNextImage()
{
if (mImagesPool.isEmpty())
return;
emit process(mImagesPool.first());
}
void Widget::onProcessed(const QImage &img)
{
if (mImagesPool.isEmpty())
return;
rawImage->setPixmap(QPixmap::fromImage(mImagesPool.takeFirst()));
processedImage->setPixmap(QPixmap::fromImage(img));
showNextImage();
}
处理器.cpp
void Processor::process(const QImage &img)
{
QImage newImg = img;
// Do stuff
emit processed(newImg);
}
关于c++ - Qt C++ - 多线程视频帧转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30077177/