'QML-Verbindungen: Nicht zuweisen nicht existierende Eigenschaft", obwohl das Gegenteil wahr ist

So, ich habe folgende Fragen, was wohl die meisten ähnlich zu meinem bestehenden problem:

QML: Mit cpp-signal in QML immer "kann Nicht zuordnen, nicht existierende Eigenschaft"

Leider nicht helfen. (Hab noch eine andere Lösung, die ich finden konnte auf stackoverflow/google/qt-Foren, etc)

Hielt ich immer folgende zwei Fehler:

qrc:/anzeigen.qml:30:9: QML-Verbindungen: Cannot assign to non-existent
Eigenschaft "onNewFrameReceived" qrc:/anzeigen.qml:31: ReferenceError:
imageProvide ist nicht definiert

Hier ist mein code (bearbeitet nach unten, um es in einen "Minimal-Beispiel').

Nur die Dateien wichtig sein sollte:

  1. main.cpp
  2. anzeigen.qml
  3. imageprovidervm.cpp
  4. imageprovidervm.h

Habe ich die imagesource Klasse, nur zur Vollständigkeit, falls jemand kompilieren möchte diese auf seinem eigenen.

Q1. Also, ich verstehe nicht, warum sogar nach der Einstellung der context-Eigenschaft in main.cpp wird die folgende Fehlermeldung angezeigt.

qrc:/anzeigen.qml:31: ReferenceError: imageProvide ist nicht definiert

Was komisch ist, ist, dass intellisense/autocomplete scheint zu erkennen, imageProvide völlig richtig.

Q2. Obwohl es in meiner imageprovider.h, ich habe Eigenschaften (newimage) und Signale (newFrameReceived), die gesehen werden sollte, in die qml-Datei, noch bekomme ich die folgende Fehlermeldung. Auch die Qt-intellisense/autocomplete schlägt fehl, zu zeigen, dass meine definiertes signal (onNewFrameReceived) hier.

qrc:/anzeigen.qml:30:9: QML-Verbindungen: Cannot assign to non-existent
Eigenschaft "onNewFrameReceived"

  • Zusätzliche info: Debuggen und stoppen an einem Haltepunkt in der qml-Datei in Zeile 31, zeigt in der "einheimischen und Ausdrücke" der qtcreator, dass ich nur 2 Signale zur Verfügung, nämlich "objectNameChanged" und "targetChanged".
    Warum ???

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#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<ImageSource>();

        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();
    }

anzeigen.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 <QQuickImageProvider>
#include <QObject>
#include "imagesource.h"

class ImageProviderVM : public QObject, public QQuickImageProvider
{
    Q_OBJECT
public:
    ImageProviderVM(std::shared_ptr<ImageSource> 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<ImageSource> m_model;
};

#endif //IMAGEPROVIDERVM_H

imageprovidervm.cpp

#include "imageprovidervm.h"
#include <functional>

#include <QPixmap>
#include <QDebug>

ImageProviderVM::ImageProviderVM()
    : QQuickImageProvider(QQuickImageProvider::Image)
{
}

ImageProviderVM::ImageProviderVM(std::shared_ptr<ImageSource> 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 <QImage>
#include <boost/signals2.hpp>

class ImageSource
{
public:
    ImageSource();
    void generateImages();
    void generatePixmaps(const QString &id, QSize *size, const QSize &requestedSize);

    typedef boost::signals2::signal<void (QPixmap)> NewPixMapDelegate;
    boost::signals2::connection subscribeNewPixMap(NewPixMapDelegate::slot_function_type f);

    typedef boost::signals2::signal<void (QImage)> 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 <QPixmap>
#include <QPainter>

#include <thread>

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);
}

und hier ist die CMake-Datei:

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")
Was passiert, wenn Sie debug "imageProvide" - Eigenschaft? Ich meine, fügen Sie ein console.log(imageProvide) einige QML-Taste oder das Menü und schauen Sie, was gedruckt wird, in der Konsole.
Und wie sollte ich in der Lage sein, das zu tun? Ich folgte diesem link und fügte hinzu, eine Funktion mit f() {} mit der Konsole.log-Anweisung. Aber wie rufe ich die Funktion? Ich folgte es hier: doc.qt.io/qt-5/qtquick-debugging.html, Aber konnte es nicht herausfinden. (Ich bin kein javascript-Programmierer.)
Versuchen engine.rootContext()->setContextProperty(...) erstellen, anstatt ein "unassociated" Kind-Kontext.
wow!!! das klappte! Aber ich verstehe nicht, warum es die nicht? Ist das nicht nur eine variable zugewiesen mit dem Wert, den bekomme ich sowieso? Ich sollte wohl prüfen Sie die QQmlContext doc Seite auf die qt-website. Vielen Dank. Es ist mein problem gelöst. Wenn Sie es post, als Antwort, ich markiere ihn als gelöst/'akzeptierte Antwort' dann.
Es ist nur eine neu erstellte untergeordnete Rahmen, kein Objekt zugeordnet ist. Um Ihnen zu helfen herauszufinden, was ist, wenn Sie erstellt einen zweiten Kontext zu? Es würde keinen Sinn machen, wenn die Objekte erstellt im root-Kontext in der Lage waren, um auf Eigenschaften zuzugreifen, die 2-Kind-zusammenhängen, ist es das gleiche für nur eine.

InformationsquelleAutor Joey Mallone | 2017-04-10

Schreibe einen Kommentar