将QImage传递给Image Provider的问题者QML

时间:2018-08-27 09:41:08

标签: c++ qt qml

我正在尝试使用Image Provider将QImage传递给QML,但始终会出现错误:

  

无法从提供程序获取图像:image:// provider / im。

我正在编写一个简单的Media Player应用程序,并且想要显示Media Player元数据中的封面图像:

  

QVariant变体= _cpp_player-> metaData(QMediaMetaData :: CoverArtImage);   QImage图片= variant.value();

我正在通过信号发送该QImage,该QImage与Image Provider类中的插槽连接。该信号还会调用main.qml中的reload函数。

这是完整的代码:

main.cpp

#include <QUrl>
#include "player.h"
#include "imageprovider.h"
#include "imageprocessor.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    Player player;

    QQmlApplicationEngine engine;
    ImageProvider *imageProvider = new ImageProvider();
    engine.rootContext()->setContextProperty("player", &player);
    engine.addImageProvider("provider", imageProvider);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
       return -1;

    return app.exec();
}

imageprovider.h

#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H

#include <QObject>
#include <QImage>
#include <QQuickImageProvider>

class ImageProvider : public QObject, public QQuickImageProvider
{
    Q_OBJECT

public:
    explicit ImageProvider(): QQuickImageProvider(QQuickImageProvider::Image) {}

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);

public slots:
    void imageChanged(QImage image);

private:
    QImage _image;

};

#endif // IMAGEPROVIDER_H

imageprovider.cpp

#include "imageprovider.h"
#include <QDebug>

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    if(_image.isNull())
    {
        qDebug() << "Image is null";
    }

    return _image;
}

void ImageProvider::imageChanged(QImage image)
{
    _image = image;
}

player.h

#ifndef PLAYER_H
#define PLAYER_H

#include <QObject>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QMediaObject>
#include <QMediaMetaData>
#include <QList>
#include <QStringList>
#include "imageprovider.h"

class Player : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString songName READ songName WRITE setSongName NOTIFY songNameChanged)
    Q_PROPERTY(QStringList list READ list NOTIFY playListUpdated)


    QMediaPlayer *_cpp_player;
    QMediaPlaylist *_cpp_playlist;
    QString _songName;
    QStringList strList;
    ImageProvider *_cpp_provider;

public:
    explicit Player(QObject *parent = nullptr);
    QString songName() const;
    QStringList list() const;
    void setSongName(const QString &songName);
    void addToPlayList(const QList<QUrl> &url);
    Q_INVOKABLE void openFileDialog();
    Q_INVOKABLE void positionChangedFromQML(const int &val);
    Q_INVOKABLE void playListPositionChanged(const int &index);

public slots:
    void playButtonClicked();
    void pauseButtonClicked();
    void stopButtonClicked();
    void nextButtonClicked();
    void previousButtonClicked();
    void currentPlayListPosition(int index);
    void positionChanged(qint64 pos);
    void durationChanged(qint64 dur);
    void stateChanged(QMediaPlayer::MediaStatus state);

signals:
    void songNameChanged();
    void posChanged(qint64 pos);
    void songDuration(qint64 dur);
    void songTime1(QString tim);
    void songTime2(QString tim2);
    void playListIsNotEmpty();
    void playListUpdated();
    void imageChanged(QImage image);
};

#endif // PLAYER_H

player.cpp

#include "player.h"
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QMediaContent>
#include <QtDebug>
#include <QDateTime>
#include <QFileDialog>


class QMediaPlaylist;
class QMediaPlayer;

Player::Player(QObject *parent) : QObject(parent)
{
    _cpp_player = new QMediaPlayer;
    _cpp_playlist = new QMediaPlaylist;
    _cpp_provider = new ImageProvider;
    _cpp_player->setPlaylist(_cpp_playlist);
    connect(_cpp_player, &QMediaPlayer::durationChanged, this, &Player::durationChanged);
    connect(_cpp_player, &QMediaPlayer::positionChanged, this, &Player::positionChanged);
    connect(this, &Player::imageChanged, _cpp_provider, &ImageProvider::imageChanged);
}

void Player::addToPlayList(const QList<QUrl> &url)
{
    for (auto &el: url) {
        _cpp_playlist->addMedia(el);
    }
}

Q_INVOKABLE void Player::openFileDialog()
{
    QFileDialog fileDialog;
    fileDialog.setFileMode(QFileDialog::ExistingFiles);
    fileDialog.setDirectory("/home");
    QStringList formatList = {"*.mp3", "*.flac", "*.wav"};
    fileDialog.setNameFilters(formatList);
    if (fileDialog.exec() == QDialog::Accepted)
    {
        addToPlayList(fileDialog.selectedUrls());
        for(int i = 0; i<fileDialog.selectedUrls().size(); ++i){
            strList.append(fileDialog.selectedUrls().at(i).fileName());
            emit playListIsNotEmpty();
            emit playListUpdated();
        }
    }
}

QString Player::songName() const
{
    return _songName;
}

QStringList Player::list() const
{
    return strList;
}

void Player::setSongName(const QString &songName)
{
    _songName = songName;
    emit songNameChanged();
}

void Player::currentPlayListPosition(int index)
{
    if(index!=-1){
        setSongName(_cpp_player->metaData(QMediaMetaData::Title).toString());
    }
}

void Player::durationChanged(qint64 dur)
{
    stateChanged(QMediaPlayer::LoadedMedia);
    emit songDuration(dur);
}

void Player::stateChanged(QMediaPlayer::MediaStatus state)
{
    if (state == QMediaPlayer::LoadedMedia){

        if (_cpp_player->isMetaDataAvailable())
        {
            setSongName(_cpp_player->metaData(QMediaMetaData::Title).toString());
            QVariant variant = _cpp_player->metaData(QMediaMetaData::CoverArtImage);
            QImage image = variant.value<QImage>();
            emit imageChanged(image);
        }
        else
        {
          qDebug() << "No metadata.";
        }
    }
}

Q_INVOKABLE void Player::positionChangedFromQML(const int &val)
{
    _cpp_player->setPosition(val);
}

void Player::playListPositionChanged(const int &index)
{
    _cpp_playlist->setCurrentIndex(index);
}

void Player::positionChanged(qint64 pos)
{

    emit posChanged(pos);
    emit songTime1(QDateTime::fromTime_t((uint)pos/1000).toUTC().toString("mm:ss"));
    emit songTime2((QDateTime::fromTime_t((uint)((_cpp_player->duration()/1000) - pos/1000))).toUTC().toString("mm:ss"));

}

void Player::playButtonClicked()
{
    if(!_cpp_playlist->isEmpty()){
        _cpp_player->play();
    }
}

void Player::pauseButtonClicked()
{
    _cpp_player->pause();
}

void Player::stopButtonClicked()
{
    _cpp_player->stop();
}

void Player::nextButtonClicked()
{
    if(_cpp_playlist->nextIndex()!=-1){
        _cpp_playlist->next();
    }
    else
    {
        _cpp_player->stop();
        _cpp_player->play();
    }
}

void Player::previousButtonClicked()
{
    if(_cpp_playlist->previousIndex()!=-1){
        _cpp_playlist->previous();
    }
    else{
        _cpp_player->stop();
        _cpp_player->play();
    }
}

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3

Window {

    Connections{
        target:  player
        onPosChanged:{
            newSlider.value = pos
        }
        onSongDuration:{
            newSlider.stepSize = 1000
            newSlider.to = dur
        }
        onSongTime1: {
            newSlider.time1 = tim;
        }
        onSongTime2:{
            newSlider.time2 = tim2;
        }
        onPlayListIsNotEmpty:{
            toolBar.playState = "playClicked"
        }
        onImageChanged:{
            cover.reload();
        }
    }

    visible: true
    width: 900
    height: 600
    title: "Media Player"

    ToolBar {
        id: toolBar
    }

    PlayListView{
        id: playList
        visible: false
    }

    AnotherSlider{
        id:newSlider
        anchors.bottom: toolBar.top
        anchors.bottomMargin: 40
        anchors.horizontalCenter: parent.horizontalCenter
        sliderWidth: toolBar.width - 40
        onMoved: {
            player.positionChangedFromQML(value)
        }
    }

    Rectangle{

        id: albumImage
        width: newSlider.width/2 - 10
        height: newSlider.width/2 - 10
        property int imageId: 0
        Image {
            id: cover
            anchors.fill:albumImage
            source: "image://provider/im"
            function reload(){
                var oldSource = source;
                source = ""
                source = oldSource
            }
        }


        color: "white"
        border.color: "black"
        border.width: 5
        radius: 5
        anchors.left: newSlider.left
        anchors.bottom: newSlider.top
        anchors.bottomMargin: 40
    }

}

怎么了?我该怎么解决?

0 个答案:

没有答案