'QML Connections: Cannot assign to non-existent Property' despite the opposite being true

So, I checked the following questions, which seemed most similar to my existing problem: QML: Using cpp signal in QML always results in "Cannot assign to non-existent property" Unfortunately that did not help. (Nor did any other solution that I could find on stackoverflow/google/qt forums, etc) I kept getting the following two errors: qrc:/view.qml:30:9: QML Connections: Cannot assign to non-existent property "onNewFrameReceived" qrc:/view.qml:31: ReferenceError: imageProvide is not defined Here is my code (edited down to make it, into a 'Minimum Working Example'). The only files important should be: main.cpp view.qml imageprovidervm.cpp imageprovidervm.h I included the imagesource class, just to be complete, in case someone wants to compile this on his own as well. Q1. So, I don't understand why even after setting the context property in main.cpp, the following error appears. qrc:/view.qml:31: ReferenceError: imageProvide is not defined What is funny is that, intellisense/autocomplete seems to detect imageProvide completely correctly. Q2. Even though in my imageprovider.h, I added properties (newimage) and signals (newFrameReceived) that should be seen in the qml file, still I get the following error. Also, the Qt intellisense/autocomplete fails to show my defined signal (onNewFrameReceived) here. qrc:/view.qml:30:9: QML Connections: Cannot assign to non-existent property "onNewFrameReceived" Additional info: Debugging and stopping on a break point in the qml file at line 31, shows in the "locals and expressions" of the qtcreator that I have only 2 signals available here, namely "objectNameChanged" and "targetChanged". Why ??? main.cpp #include #include #include #include "imageprovidervm.h" #include "imagesource.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; QQmlContext *context = new QQmlContext(engine.rootContext()); auto model = std::make_shared(); auto vm = new ImageProviderVM(model); engine.addImageProvider(QLatin1String("imageProvider"), vm); context->setContextProperty("imageProvide", vm ); model->generateImages(); engine.load(QUrl(QStringLiteral("qrc:/view.qml"))); return app.exec(); } view.qml import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQml.Models 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Window 2.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("&Open") onTriggered: console.log("Open action triggered"); } MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } Rectangle { Connections { target: imageProvide onNewFrameReceived: image.reload(); } anchors.fill: parent Column { Image { id: image source: "image://imageProvider/images.jpeg?id=" + Math.random() cache: false asynchronous: true function reload() { var oldSource = source; source = ""; source = oldSource; } } } } Label { text: qsTr("Hello World") anchors.centerIn: parent } } imageprovidervm.h #ifndef IMAGEPROVIDERVM_H #define IMAGEPROVIDERVM_H #include #include #include "imagesource.h" class ImageProviderVM : public QObject, public QQuickImageProvider { Q_OBJECT public: ImageProviderVM(std::shared_ptr model); ~ImageProviderVM(); virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override; virtual QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize) override; // Properties Q_PROPERTY(QImage newimage READ getNewImage NOTIFY newFrameReceived) // Signals signals: void newFrameReceived(); private: QImage getNewImage() const; QPixmap m_pixmap; QImage m_image; std::shared_ptr m_model; }; #endif // IMAGEPROVIDERVM_H imageprovidervm.cpp #include "imageprovidervm.h" #include #include #include ImageProviderVM::ImageProviderVM() : QQuickImageProvider(QQuickImageProvider::Image) { } ImageProviderVM::ImageProviderVM(std::shared_ptr model) : QQuickImageProvider (QQuickImageProvider::Image) , m_pixmap() , m_model(model) { m_model->subscribeNewPixMap([this](QPixmap pixmap) { qDebug() << "setting m_pixmap"; if (pixmap.size().isValid()) { m_pixmap = pixmap; } else qDebug() << "is it NULL ??? " << pixmap.isNull(); }); m_model->subscribeNewImage([this](QImage image) { qDebug() << "setting m_image"; if (image.size().isValid()) { m_image = image; emit newFrameReceived(); } else qDebug() << "is it NULL ??? " << image.isNull(); }); qDebug() << "imageproviderVM constructed"; } ImageProviderVM::~ImageProviderVM() { } QPixmap ImageProviderVM::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) { // look into the parameters id, size and requestedSize once the rest of the structure is there return m_pixmap; } QImage ImageProviderVM::requestImage(const QString & id, QSize * size, const QSize & requestedSize) { return m_image; } QQuickTextureFactory * ImageProviderVM::requestTexture(const QString & id, QSize * size, const QSize & requestedSize) { // return QQuickTextureFactory::createTexture(); } QImage ImageProviderVM::getNewImage() const { return m_image; } imagesource.h #ifndef IMAGESOURCE_H #define IMAGESOURCE_H #include #include class ImageSource { public: ImageSource(); void generateImages(); void generatePixmaps(const QString &id, QSize *size, const QSize &requestedSize); typedef boost::signals2::signal NewPixMapDelegate; boost::signals2::connection subscribeNewPixMap(NewPixMapDelegate::slot_function_type f); typedef boost::signals2::signal NewImageDelegate; boost::signals2::connection subscribeNewImage(NewImageDelegate::slot_function_type f); private: NewPixMapDelegate m_newPixMap; NewImageDelegate m_newImage; }; #endif // IMAGESOURCE_H imagesource.cpp #include "imagesource.h" #include #include #include ImageSource::ImageSource() { } boost::signals2::connection ImageSource::subscribeNewImage(NewImageDelegate::slot_function_type f) { return m_newImage.connect(f); } void ImageSource::generateImages() { std::thread t([this]() { auto image = QImage("/home/junaid/testing_ground/fourthtime/images.jpeg"); m_newImage(image); /// useless wait. just simulating that another image comes after sometime and so on onwards. int random_wait = 2; //sec sleep(random_wait); image = QImage("/home/junaid/Downloads/pnggrad16rgb.png"); m_newImage(image); }); t.detach(); } boost::signals2::connection ImageSource::subscribeNewPixMap(NewPixMapDelegate::slot_function_type f) { return m_newPixMap.connect(f); } void ImageSource::generatePixmaps(const QString &id, QSize *size, const QSize &requestedSize) { int width = 100; int height = 50; if (size) { *size = QSize(width, height); } QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width, requestedSize.height() > 0 ? requestedSize.height() : height); pixmap.fill(QColor(id).rgba()); // write the color name QPainter painter(&pixmap); QFont f = painter.font(); f.setPixelSize(20); painter.setFont(f); painter.setPen(Qt::black); if (requestedSize.isValid()) painter.scale(requestedSize.width() / width, requestedSize.height() / height); painter.drawText(QRectF(0, 0, width, height), Qt::AlignCenter, id); m_newPixMap(pixmap); } and here is the CMake file: cmake_minimum_required(VERSION 2.8.12) project(non_existent_property LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt5 COMPONENTS Core Quick REQUIRED) file( GLOB SRCS *.cpp *.h ) add_executable(${PROJECT_NAME} "qml.qrc" ${SRCS}) target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick "pthread")
Take Your Experience to the Next Level
NewDownload our mobile app for a faster and better experience.
Comments
0U
Join the discussion
Sign in to leave a comment