我正在尝试使用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
}
}
怎么了?我该怎么解决?