• 4348阅读
  • 15回复

zhengtianzuo系列-QmlImageProvider [复制链接]

上一主题 下一主题
离线zhengtianzuo
 

只看楼主 倒序阅读 楼主  发表于: 2017-10-14
关于 QQuickImageProvider 官方的描述
The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.

有时候希望将QPixmap或者QImage中的图像显示到Qml中, 这时候就需要用到QQuickImageProvider了
继承QQuickImageProvider 新建一个类:


```
class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider::ImageProvider(ImageType type, Flags flags = Flags()) :
        QQuickImageProvider(type, flags)
    {
    }
    ~ImageProvider(){}
    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
    {
        QString strFileName = QCoreApplication::applicationDirPath() + "/" + id;
        qDebug() << strFileName;
        QPixmap pixmap(strFileName);
        return pixmap;
    }
};
```


使用:

加载qml文件之前先设置addImageProvider

```
    QQmlApplicationEngine engine;
    engine.addImageProvider(QLatin1String("imageProvider"), new ImageProvider(QQmlImageProviderBase::Pixmap));
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
```

在qml文件中使用

```
    Image {
        anchors.centerIn: parent
        source: "image://imageProvider/Face.png"
    }
```


其中image://imageProvider/后面的字符串会被读取到上面requestPixmap中的id中. 这样我们可以根据ID来加载不同的Image. 代码中是读取本地一个Face.png的文件名.



需要完整代码请访问 QtQuickExamples
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线自强不吸

只看该作者 1楼 发表于: 2017-10-16
这个玩意有个bug,图片加载多了容易挂掉,需要做下处理
自强不吸!
离线angelus

只看该作者 2楼 发表于: 2017-10-16
建议直接自己写一个新的qml组件,直接用来显示图片数据,使用提供者问题还是有点多,特别是在需要大数据量更新的时候!
离线zhengtianzuo

只看该作者 3楼 发表于: 2017-10-16
回 自强不吸 的帖子
自强不吸:这个玩意有个bug,图片加载多了容易挂掉,需要做下处理 (2017-10-16 09:04) 

我正式项目里也在大量用啊 没有出现崩溃什么的啊
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线zhengtianzuo

只看该作者 4楼 发表于: 2017-10-16
回 angelus 的帖子
angelus:建议直接自己写一个新的qml组件,直接用来显示图片数据,使用提供者问题还是有点多,特别是在需要大数据量更新的时候! (2017-10-16 09:12) 

大数据量更新的 我正式项目里就在用 没有什么问题啊
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线自强不吸

只看该作者 5楼 发表于: 2017-10-16
回 zhengtianzuo 的帖子
zhengtianzuo:我正式项目里也在大量用啊 没有出现崩溃什么的啊[表情] (2017-10-16 10:23) 

good ,正好请教一下
自强不吸!
离线自强不吸

只看该作者 6楼 发表于: 2017-10-16
我读图片用的Qimagereader,显示用的GridView,界面滑动太快了就有死的可能,一般是死在emit finished();这里
自强不吸!
离线zhengtianzuo

只看该作者 7楼 发表于: 2017-10-16
回 自强不吸 的帖子
自强不吸:我读图片用的Qimagereader,显示用的GridView,界面滑动太快了就有死的可能,一般是死在emit finished();这里
 (2017-10-16 16:56) 

代码贴出来 一起帮你分析分析呢
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线angelus

只看该作者 8楼 发表于: 2017-10-16
回 zhengtianzuo 的帖子
zhengtianzuo:大数据量更新的 我正式项目里就在用 没有什么问题啊[表情] (2017-10-16 10:24) 

比如截屏1080p的图片在每秒20帧的更新在image里边!
意思就是每秒更新20张图片的数据量
离线zhengtianzuo

只看该作者 9楼 发表于: 2017-10-17
回 angelus 的帖子
angelus:比如截屏1080p的图片在每秒20帧的更新在image里边!
意思就是每秒更新20张图片的数据量 (2017-10-16 19:39) 

问题是什么 运行一段时间崩溃了? 代码是什么样的呢?
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线自强不吸

只看该作者 10楼 发表于: 2017-10-18
代码是这样的,qml里面是个gridview,我从文件夹里读出图片路径放到gridview,gridview滑动快了就死了
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H

#include <QQuickImageProvider>
#include <QSize>
#include <QDebug>
#include <QImage>
#include <QThreadPool>

#include <QImageReader>

class AsyncImageResponse : public QQuickImageResponse, public QRunnable
{
  public:
      AsyncImageResponse(const QString &id, const QSize &requestedSize)
       : m_id(id), m_requestedSize(requestedSize), m_texture(0)
      {
          setAutoDelete(false);
      }

      QQuickTextureFactory *textureFactory() const
      {
          return m_texture;
      }

      //图片自适应窗口
      QSize resizeImage(const QSize image,int w,int h)
      {
          double width,height;

          double setWidth = (double)w;
          double setHeight = (double)h;
          // 缩放图片尺寸以适应屏幕大小
          double imageWidth = (double)image.width();
          double imageHeight = (double)image.height();

          if(setWidth/imageWidth<=setHeight/imageHeight){
              width=imageWidth*(setWidth/imageWidth);
              height=imageHeight*(setWidth/imageWidth);
          }else{
              width=imageWidth*(setHeight/imageHeight);
              height=imageHeight*(setHeight/imageHeight);
          }

          return QSize((int)width,(int)height);
      }

      void run()
      {
          QImage image(80,80, QImage::Format_RGB32);
          QImageReader imageReader;
          //QImage image;
          imageReader.setFileName(m_id);
          //qDebug()<<"read Image "<<m_id;
          QSize Size = resizeImage(imageReader.size(),m_requestedSize.width(),m_requestedSize.height());//压缩读取

          if (imageReader.canRead())
          {
              imageReader.setScaledSize(Size);//设置缩放大小;
              image = imageReader.read();// 读取图片
              //m_texture = QQuickTextureFactory::textureFactoryForImage(image);
              //emit finished();
          }
          else
          {
              // 获取错误信息
              QImageReader::ImageReaderError error = imageReader.error();
              QString strError = imageReader.errorString();
              qDebug() << "Last Error : " << strError <<error;

              if (m_requestedSize.isValid())
                  image = image.scaled(m_requestedSize);
              image.fill(QColor("green"));
          }

          m_texture = QQuickTextureFactory::textureFactoryForImage(image);
          emit finished();
      }

      QString m_id;
      QSize m_requestedSize;
      QQuickTextureFactory *m_texture;
      //QImageReader imageReader;
};

class AsyncImageProvider : public QQuickAsyncImageProvider
{
public:
    AsyncImageProvider(const int maxCount = 8)
    {
        pool.setMaxThreadCount(maxCount);
    }

    QQuickImageResponse *requestImageResponse(const QString &id,const QSize &requestedSize)
    {
      AsyncImageResponse *response = new AsyncImageResponse(id, requestedSize);
      //pool.tryStart(response);
      pool.start(response);
      return response;
    }

private:
  QThreadPool pool;
};
#endif // IMAGEPROVIDER_H

自强不吸!
离线zhengtianzuo

只看该作者 11楼 发表于: 2017-10-18
回 自强不吸 的帖子
自强不吸:代码是这样的,qml里面是个gridview,我从文件夹里读出图片路径放到gridview,gridview滑动快了就死了
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H
#include <QQuickImageProvider>
....... (2017-10-18 09:49) 

测试一下:
1. AsyncImageProvider(const int maxCount = 8) 加大maxCount的值是否就会缓解或者不出现死了?
2. AsyncImageResponse *response = new AsyncImageResponse(id, requestedSize); 尝试将AsyncImageResponse实例资源作为长期的存在试试
3. gridview滑动快了就死了, 具体是程序ui假死还是崩溃?
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线自强不吸

只看该作者 12楼 发表于: 2017-10-18
1.增大maxCount只会加大cpu的压力,而且在板子上跑,资源本来有限
2.AsyncImageResponse实例资源作为长期的存在没法实现啊,线程池是不是还得知道那个当前是空闲的?
3.直接崩溃
自强不吸!
离线zhengtianzuo

只看该作者 13楼 发表于: 2017-10-18
回 自强不吸 的帖子
自强不吸:1.增大maxCount只会加大cpu的压力,而且在板子上跑,资源本来有限
2.AsyncImageResponse实例资源作为长期的存在没法实现啊,线程池是不是还得知道那个当前是空闲的?
3.直接崩溃 (2017-10-18 11:14) 

崩溃的原因找到了吗?
博客地址: https://blog.csdn.net/zhengtianzuo06
Github: https://github.com/zhengtianzuo
个人产品: https://github.com/zhengtianzuo/Silk
产品网站: http://www.camelstudio.cn
离线自强不吸

只看该作者 14楼 发表于: 2017-10-18
回 zhengtianzuo 的帖子
zhengtianzuo:崩溃的原因找到了吗? (2017-10-18 11:23) 

在emit finished();这里挂掉的
自强不吸!
离线big_mouse

只看该作者 15楼 发表于: 2020-04-22
快速回复
限100 字节
 
上一个 下一个