如何使用C ++模型填充播放列表qml类型?

时间:2019-06-01 11:15:28

标签: c++ qt qml qtmultimedia

我正在构建音乐播放器,需要使用以下c ++模型自动填充播放列表:

static QStringList pathList;   
int main(int argc, char *argv[]){
// ...
// ...
QDirIterator it("E:/", QStringList() << "*.mp3", QDir::Files, QDirIterator::Subdirectories);
        while (it.hasNext()){
            pathList.append(it.next());
        }
    QQmlContext *ctxt1 = engine.rootContext();
    ctxt1->setContextProperty("pathModel", QVariant::fromValue(pathList)); //used model pathmodel
// ...
// ...
}

和我在qml端的播放列表代码:

Rectangle{
    width: page.width
    height: page.height
    Audio {
           id: player;
           playlist: Playlist {
               id: playlist
               PlaylistItem { source: "song1.ogg"; } //I want this process to be automated instead of doing it manually
           }
       }
       ListView {
           model: playlist;
           delegate: Text {
               font.pixelSize: 16;
               text: source;
           }
       }
       MouseArea {
           anchors.fill: parent;
           onPressed: {
               if (player.playbackState != Audio.PlayingState) {
                   player.play();
               } else {
                   player.pause();
               }
           }
       }
}

我尝试使用App列表视图类型,但只设法在单击时播放/暂停一首歌曲,无法实现诸如当歌曲结束时自动播放下一个歌曲或在选择另一首歌曲时停止当前播放等功能。 qt文档尚不清楚需要做什么,也没有可用的教程或演示

1 个答案:

答案 0 :(得分:0)

有几种解决方案取决于您要实现的目标:

  • 如果仅打算在开始时加载列表,则应该只使用QList:
// ...
QList<QUrl> sources;
QString folder = "E:/"
QDirIterator it(folder, QStringList() << "*.mp3", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
    sources << QUrl::fromLocalFile(it.next());
}
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("sources", QVariant::fromValue(sources));
// ...
// ...
Audio {
    id: player;
    playlist: Playlist {
        id: playlist
        Component.onCompleted: playlist.addItems(sources)
    }
}
// ...
  • 如果要在程序执行期间添加和删除项目,则可以使用模型:
class SourceModel: public QStandardItemModel{
    Q_OBJECT
public:
    enum SourceRoles{
        SourceRole = Qt::UserRole + 1000
    };
    SourceModel(QObject *parent=nullptr):
        QStandardItemModel(parent)
    {
        QHash<int, QByteArray> roles;
        roles[SourceRole] = "source";
        setItemRoleNames(roles);
        connect(this, &QAbstractItemModel::rowsInserted, this, &SourceModel::onRowsInserted);
        connect(this, &QAbstractItemModel::rowsRemoved, this, &SourceModel::onRowsRemoved);
        connect(this, &QAbstractItemModel::modelReset, this, &SourceModel::reset);
    }
    void addSource(const QUrl & url){
        QStandardItem *item = new QStandardItem();
        item->setData(url, SourceRole);
        appendRow(item);
    }
Q_SIGNALS:
    void sourcesInserted(int first, QList<QUrl> sources);
    void sourcesRemoved(int first, int last);
    void reset();
private:
    void onRowsInserted(const QModelIndex &parent, int first, int last){
        QList<QUrl> sources;
        for (int i=first; i <= last; ++i) {
            QModelIndex ix = this->index(i, 0, parent);
            QVariant v = data(ix, SourceRole);
            sources << v.toUrl();
        }
        Q_EMIT sourcesInserted(first, sources);
    }
    void onRowsRemoved(const QModelIndex & /*parent*/, int first, int last){
        Q_EMIT sourcesRemoved(first, last);
    }
};

// ...
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("source_model", &source_model);
// ...
QString folder = "E:/"
QDirIterator it(folder, QStringList() << "*.mp3", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
    source_model.addSource(QUrl::fromLocalFile(it.next()));
}
// ...
// ...
Connections{
    target: source_model
    onSourcesInserted: playlist.insertItems(first, sources)
    onSourcesRemoved: playlist.removeItems(first, last);
    onReset: playlist.clear()
}
Audio {
    id: player;
    playlist: Playlist {
        id: playlist
    }
}
// ...
  • 另一种选择是使用Q_PROPERTY:
class SourceManager: public QObject{
    Q_OBJECT
    Q_PROPERTY(QList<QUrl> sources READ sources  WRITE setSources  NOTIFY sourcesChanged)
public:
    using QObject::QObject;
    QList<QUrl> sources() const{
        return m_sources;
    }
    void setSources(QList<QUrl> sources){
        if (m_sources == sources)
            return;
        m_sources = sources;
        emit sourcesChanged();
    }
Q_SIGNALS:
    void sourcesChanged();
private:
    QList<QUrl> m_sources;
};
// ...
SourceManager source_manager;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("source_manager", &source_manager);
// ...
QList<QUrl> sources;
QString folder = "E:/"
QDirIterator it(folder, QStringList() << "*.mp3", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
    sources << QUrl::fromLocalFile(it.next());
}
source_manager.setSources(sources);
// ...
// ...
Connections{
    target: source_manager
    onSourcesChanged: {
        playlist.clear();
        playlist.addItems(source_manager.sources)
    }
}
Audio {
    id: player;
    playlist: Playlist {
        id: playlist
    }
}
// ...