Как обновить подкласс QPaintedTextureImage из QML - Свойство 'update' объекта QPaintedTextureImage не является функцией - PullRequest
0 голосов
/ 01 февраля 2019

Я хочу отобразить поток изображений с устройства захвата в Qt3D (через текстуру).

Итак, я вложил в подкласс QPaintedTextureImage:

#include <Qt3DRender/QPaintedTextureImage>
#include <QPainter>
#include <QImage>
#include <QPaintDevice>
#include <opencv2/opencv.hpp>

class OpenCVCaptureImage : public Qt3DRender::QPaintedTextureImage
{
public:
    explicit OpenCVCaptureImage(Qt3DCore::QNode *parent = nullptr);
    void paint(QPainter *painter) override;

private:
    cv::VideoCapture cap_;
};

OpenCVCaptureImage::OpenCVCaptureImage(Qt3DCore::QNode *parent)
    : Qt3DRender::QPaintedTextureImage(parent),
      cap_(0)
{
}

void OpenCVCaptureImage::paint(QPainter *painter)
{
    cv::Mat frame;
    cap_ >> frame;
    QImage im(static_cast<uchar *>(frame.data), frame.cols, frame.rows, int(frame.step), QImage::Format_RGB888);
    if(im.isNull()) return;
    setSize(im.size());
    //int w = painter->device()->width();
    //int h = painter->device()->height();
    painter->drawImage(0, 0, im);
}

Согласно документация :

A QPaintedTextureImage должна быть разделена на подклассы, а виртуальная функция paint () должна быть реализована.Каждый раз, когда update () вызывается для QPaintedTextureImage, вызывается функция paint () и полученное изображение загружается.

Поэтому я добавляю Timer к своей сценедерево, и в слоте onTriggered я вызываю capImage.update(), но что-то идет не так во время выполнения:

2019-01-31 22: 48: 54.865282 + 0100 Qt3DOpenCV [50001:4569220] qrc: /MyScene.qml: 57: TypeError: Свойство 'update' объекта Qt3DRender :: QPaintedTextureImage (0x106ef6bf0) не является функцией

main.cpp:

#include <QGuiApplication>
#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include "opencvcaptureimage.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    qmlRegisterType<OpenCVCaptureImage>("OpenCVCaptureImage", 1, 0, "OpenCVCaptureImage");

    QGuiApplication app(argc, argv);

    Qt3DExtras::Quick::Qt3DQuickWindow view;
    view.setSource(QUrl("qrc:/MyScene.qml"));
    view.show();

    return app.exec();
}

MyScene.qml:

import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
import OpenCVCaptureImage 1.0
import QtQml 2.12

Entity {
    id: sceneRoot

    RenderSettings {
        id: renderSettings
        activeFrameGraph: ForwardRenderer {
            clearColor: Qt.rgba(0, 0.5, 1, 1)
            camera: Camera {
                id: objectsCamera
                projectionType: CameraLens.PerspectiveProjection
                fieldOfView: 45
                aspectRatio: 16/9
                nearPlane : 0.1
                farPlane : 1000.0
                position: Qt.vector3d( 0.0, 0.0, -40.0 )
                upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
                viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
            }
        }
    }

    InputSettings {
        id: inputSettings
    }

    components: [renderSettings, inputSettings]

    PlaneMesh {
        id: planeMesh
        width: 2
        height: 2
    }

    TextureMaterial {
        id: planeMaterial
        texture: Texture2D {
            id: planeTexture
            textureImages: [
                OpenCVCaptureImage {
                    id: capImage
                }
            ]
        }
    }

    Timer {
        interval: 500
        running: true
        repeat: true
        onTriggered: capImage.update()
    }

    Transform {
        id: planeTransform
        rotationX: 90
    }

    Entity {
        id: planeEntity
        components: [ planeMesh, planeMaterial, planeTransform ]
    }
}

РЕДАКТИРОВАТЬ: Я также попытался поместить таймер в конструктор C ++:

OpenCVCaptureImage::OpenCVCaptureImage(Qt3DCore::QNode *parent)
    : Qt3DRender::QPaintedTextureImage(parent),
      cap_(0)
{
    QTimer::singleShot(2500, [=] {
        auto t = new QTimer(this);
        connect(t, &QTimer::timeout, [=] {
            this->update();
        });
        t->setInterval(200);
        t->start();
    });
}

в этом случае программа падаетQPainter::drawImage, и эта ошибка выводится на консоль:

2019-02-01 11: 15: 45.754907 + 0100 Qt3DOpenCV [55788: 4839633] QPaintDevice: Невозможно уничтожить устройство рисования, котороерисуется

1 Ответ

0 голосов
/ 01 февраля 2019

Я не совсем уверен, что вы делаете неправильно, но я успешно использовал QPaintedTextureImage в в этом примере и добавил таймер, который периодически обновляет текстуру.Qt3D не называет это напрямую, но вы можете, как вы предложили в своем вопросе.Возможно, попробуйте очистить проект, затем запустите qmake и соберите его позже.

...