如何在QQuickPaintedItem中以有效的方式绘制顺序图像

A.J*_*A.J 3 qt qgraphicsscene qquickitem

出于某种原因,我需要将 opencv VideoCapture 包装在一个将在 Qt Quick 中使用的类中。

有两个类,一个是Camera,另一个是CameraView。CameraView 继承自 QQuickPaintedItem。

相机类将定期获取图像。它通过 QObject::startTimer(int interval) 实现。(例如,如果网络摄像头的 fps 为 30,则计时器间隔为 1000 / 30 - 8,8 是时间偏差)。一旦 Camera 获取到图像,它会通过调用 CameraView::Update() 通知 CameraView 重新绘制。

而在 CameraView::paint(QPainter *) 中,CameraView 将从 Camera 类获取图像的副本并通过调用 QPainter::drawImage(...) 绘制该图像。

我在编码过程中遇到了一些问题:

  1. 我尝试用 QThread 替换时间事件以定期从相机获取图像。当我在 QThread 中调用 CameraView::Update() 时,CameraView 不会重新绘制。问题是什么?

  2. 在我的笔记本电脑中,当我让 CameraView 全屏绘制图像时,我发现一个 Python 程序变慢了。是另一种低成本高效的绘画方式吗?

Ale*_*r V 5

如何基于 QQuickPaintedItem C++ 类高效更新 QML 项?我将一些预处理委托给专用线程而不是 UI 线程上的计时器,并且它不再更新 QML UI 中的图像。

从 Qt 中的 UI 线程(包括 QML)触发 UI 更新是强制性的。使该 CameraView 公开公共插槽updateImage

class CameraView : public QQuickPaintedItem
{
    Q_OBJECT
    Q_DISABLE_COPY(CameraView)

public:
    CameraView(QQuickItem* parent = nullptr);

public slots:
    void updateImage(const QImage&);

protected:
    QImage m_image;
};
Run Code Online (Sandbox Code Playgroud)

CameraView 应该实现updateImagepaint像这样:

void CameraView::updateImage(const QImage& image)
{
    m_imageThumb = image; // does shallow copy of image data
    update();             // triggers actual update
}

void CameraView::paint(QPainter* painter)
{
    painter->drawImage(this->boundingRect(), m_image);
}
Run Code Online (Sandbox Code Playgroud)

OpenCvOnWorkerThread应该启动它的工作线程并暴露 signalUiUpdate:

OpenCvOnWorkerThread::OpenCvOnWorkerThread()
{
    this->moveToThread(&m_workerThread);
    // the below will allow communication between threads
    connect(this, SIGNAL(signalUiUpdate(QImage)), m_cameraView, SLOT(updateImage(QImage)));

    m_workerThread.start();
}

void OpenCvOnWorkerThread::cvRead()
{
     QImage image;

     // OpenCV details available in your code
     // cv::read
     // make QImage from frame


     // deliver QImage to another thread
     emit signalUiUpdate(image);
}
Run Code Online (Sandbox Code Playgroud)

更新:在我自己的“相机”线程类似 QML 输出的代码中,我还负责在无法处理视频帧时处理 UI 线程停顿,以便信号发送者知道何时不发布视频帧。但这值得另一个问题。或者可以在没有信号和槽但有条件变量的情况下重新实现整个示例。