我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
}
}