我shared_ptr<Track>通过 setContextProperty 将 a 传递给 QtQuick2ApplicationViewer。然后将传递的值 (inputStream) 分配给 PianoRoll 的属性,这是一个自定义 QQuickItem,其属性流类型为shared_ptr<Track>。
我收到以下错误消息:
PianoRollDemo.qml:10: unable to assign shared_ptr<Track> to [unknown property type]
主文件
Q_DECLARE_METATYPE(shared_ptr<Track>)
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    // qmlRegisterType<Track>("Track", 1, 0, "Track");
    qmlRegisterType<PianoRoll>("PianoRoll", 1, 0, "PianoRoll");
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/Diplomarbeit/PianoRollDemo.qml"));
    viewer.showExpanded();
    if (argc >= 2)
    {
        if (strcmp(argv[1],"-readFile") == 0)
        {
            string fileName = argv[2];
            cout << "Reading from file " << fileName << endl;
            GP5Reader reader;
            MainGame mainGame;
            reader.read(mainGame.score, fileName);
            mainGame.playerInputs.push_back(shared_ptr<Track>(new Track(0)));
            mainGame.onPlayerInput(0, shared_ptr<Note>(new Note(295309, 100, 69, 92)));
            mainGame.onPlayerInput(0, shared_ptr<Note>(new Note(295306, 100, 64, 92)));
            mainGame.onPlayerInput(0, shared_ptr<Note>(new Note(295300, 100, 57, 92)));
            mainGame.onPlayerInput(0, shared_ptr<Note>(new Note(295315, 100, 45, 92)));
        }
        else if(strcmp(argv[1],"-listenToMidi") == 0)
        {
            int port = atoi(argv[2]);
            cout << "Listening to port " << port << endl;
            MidiInput* midiIn = new MidiInput();
            midiIn->listen(port);
            viewer.rootContext()->setContextProperty("inputStream", QVariant::fromValue(midiIn->track));
            /*
            QDeclarativeView view;
            QUrl url = QUrl::fromLocalFile("qml/Diplomarbeit/PianoRollDemo.qml");
            bool valid = url.isValid();
            view.setSource(url);
            view.show();
            */
        }
    }
    else
    {
        cout << "No arguments received." << endl;
    }
    #ifdef Q_OS_ANDROID
        GP5Reader reader;
        Score score;
        reader.read(score, "/storage/emulated/0/test.gp5");
    #endif
    return app.exec();
}
钢琴卷
#ifndef PIANOROLL_H
#define PIANOROLL_H
#include <QQuickItem>
#include <QSGGeometry>
#include <QSGFlatColorMaterial>
#include <track.h>
class PianoRoll : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(shared_ptr<Track> stream READ stream WRITE setStream NOTIFY streamChanged)
public:
    PianoRoll(QQuickItem* parent = 0);
    // Get Methods
    shared_ptr<Track> stream() const;
    // Set Methods
    void setStream(shared_ptr<Track> stream);
protected:
    QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data);
private:
    shared_ptr<Track> m_stream;
    QSGGeometry m_geometry;
    QSGFlatColorMaterial m_material;
signals:
    void streamChanged();
};
QML_DECLARE_TYPE(PianoRoll)
#endif // PIANOROLL_H
钢琴卷曲.cpp
#include <QQuickItem>
#include <QSGGeometry>
#include <QSGFlatColorMaterial>
#include <QSGGeometryNode>
#include <QSGSimpleRectNode>
#include <iostream>
#include <memory>
#include "pianoroll.h"
#include "note.h"
using namespace std;
PianoRoll::PianoRoll(QQuickItem *parent) :
    QQuickItem(parent),
    m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4),
    m_stream(new Track)
{
    // Important, otherwise the paint method is never called
    setFlag(ItemHasContents);
    m_material.setColor(Qt::red);
    // TODO: remove TestData
    shared_ptr<Note> noteOn1(new Note(0, 500, 70, 100));
    shared_ptr<Note> noteOn2(new Note(500, 500, 40, 100));
    shared_ptr<Note> noteOn3(new Note(1000, 200, 30, 100));
    m_stream->addNote(noteOn1);
    m_stream->addNote(noteOn2);
    m_stream->addNote(noteOn3);
    //m_stream.addNoteEvent(new NoteEvent(700, 700, 70, 100));
}
shared_ptr<Track> PianoRoll::stream() const
{
    return m_stream;
}
void PianoRoll::setStream(shared_ptr<Track> stream)
{
    if (m_stream == stream) return;
    m_stream = stream;
    emit streamChanged();
    update();
}
QSGNode *PianoRoll::updatePaintNode(QSGNode *n, QQuickItem::UpdatePaintNodeData *data)
{
    QSGGeometryNode *node = static_cast<QSGGeometryNode *>(n);
    if (!node)
    {
        node = new QSGSimpleRectNode(boundingRect(), Qt::white);
    }
    node->removeAllChildNodes();
    qreal msPerScreen = 10000;
    qreal pitchesPerScreen = 128;
    qreal x_factor = (qreal) boundingRect().width() / msPerScreen;
    qreal y_factor = (qreal) boundingRect().height() / pitchesPerScreen;
    for (unsigned int i = 0; i < m_stream->notes.size(); i++)
    {
        shared_ptr<Note> note = m_stream->notes.at(i);
        qreal left = boundingRect().left() + note->getTime() * x_factor;
        qreal top = boundingRect().top() + note->getPitch() * y_factor;
        qreal width = note->getDuration() * x_factor;
        qreal height = y_factor;
        QRectF noteRectangle = QRectF(left, top, width, height);
        node->appendChildNode(new QSGSimpleRectNode(noteRectangle, Qt::black));
    }
    return node;
}
轨道.h
#ifndef NOTESTREAM_H
#define NOTESTREAM_H
#include <vector>
#include <memory>
#include <QVariantList>
#include <QQuickView>
#include "note.h"
using namespace std;
class Track : public QObject
{
public:
    void print();
    //TODO: private:
    QList<shared_ptr<Note>> notes;
    int gMInstrument;
    int trackIndex;
    int stringCount;
    vector<int> tuning;
    bool operator==(Track& other) const;
    Track(int trackIndex = -1);
    ~Track();
public slots:
    void addNote(shared_ptr<Note> note);
signals:
};
#endif // NOTESTREAM_H
轨道.cpp
#include <vector>
#include <memory>
#include <iostream>
#include <QMetaType>
/*
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/QDeclarativeContext>
*/
#include <QQuickView>
#include <QQmlContext>
#include <qqml.h>
#include "track.h"
#include "note.h"
using namespace std;
void Track::print()
{
    for (unsigned int i = 0; i < notes.size(); i++)
    {
        shared_ptr<Note> event = notes.at(i);
        cout << event->getTime() << "  Pitch: " << event->getPitch() << endl;
    }
    cout << notes.size() << " notes" << endl;
}
bool Track::operator==(Track &other) const
{
    return other.notes == this->notes;
}
Track::Track(int trackIndex)
{
    this->trackIndex = trackIndex;
}
Track::~Track()
{
}
void Track::addNote(shared_ptr<Note> note)
{
    //print();
    this->notes.append(note);
    /*
    listElems.append(QVariant::fromValue(new NoteEvent(1, 1, 1, 1)));
    view->rootContext()->setContextProperty("dataModel",QVariant::fromValue(listElems));
    */
}
PianoRollDemo.qml
import QtQuick 2.0
import PianoRoll 1.0
Rectangle {
    width: 500
    height: 200
    PianoRoll {
        stream: inputStream
        anchors.fill: parent
    }
}