近期学习使用QML和制作一些UI界面,需要动态的进行图片显示指定文件夹内的图片。CSDN有一些其他推荐跟着写了写,发现还是有些坑存在。特此记录。
参考了一些方法,比如
踩坑记录:QML加载图片资源_qml 怎么读取图片的exif-CSDN博客
静态加载无法实现实时改变显示的图片内容。
qml中动态加载图片(Image与QQuickImageProvider)-CSDN博客
我们需要使用
QQuickImageProvider
The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.
继承QQuickImageProvider类来实现qml中动态加载图片的方法.
目录
paintitem.h
其中我还需要一些对图片的处理,使用了opencv库,有同样需要可以参考。
- #define PAINTITEM_H
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- class PaintItem : public QQuickPaintedItem
- {
- Q_OBJECT
- public:
- explicit PaintItem(QQuickItem *parent = nullptr);
- cv::Mat get_cutted_cvimage(const cv::Mat& image, int weight_start, int weight_end, int height_start, int height_end);
-
- Q_INVOKABLE void show_image_test(int imageIndex, qreal width, qreal height);
-
- public slots:
- void updateImage(const QImage &image);
-
- protected:
- void paint(QPainter *painter) override;
-
- private:
- QImage m_imageThumb;
- QString folderPath = "/image";
- int defaultImageIndex = 1;
- };
-
- extern PaintItem *ptr_paint_image;
- #endif // PAINTITEM_H
paintitem.cpp
- #include "paintitem.h"
- #include
- #include
-
- PaintItem::PaintItem(QQuickItem *parent) : QQuickPaintedItem(parent)
- {
- }
- //更新图片
- void PaintItem::updateImage(const QImage &image)
- {
- m_imageThumb = image;
- update(); //这是库函数
- }
-
- //重要函数,qml中显示图片是用该函数
- void PaintItem::paint(QPainter *painter)
- {
- if (!m_imageThumb.isNull()) {
- QRectF targetRect = boundingRect();
- painter->drawImage(targetRect, m_imageThumb, m_imageThumb.rect()); // Draw without scaling again
- }
- else
- QuaeroDebug() << "invalied painted image --- NULL";
- }
- //这个函数是qml中调用,实现图片的格式转换等主要工作。其中get_cutted_cvimage是我的图像处理函数,删掉即可。(已删除)
- void PaintItem::show_image_test(int imageIndex, qreal width, qreal height)
- {
- try{
- QString fileName = QString("%1/cell%2.png").arg(folderPath).arg(imageIndex);
- cv::Mat image = cv::imread(fileName.toStdString());
-
- if (image.empty()) {
- QuaeroDebug() << "invalied painted image --- NULL";
- return;
- }
-
- // 如果 width 或 height 为 -1,则使用图像的原始尺寸
- if (width == -1 || height == -1) {
- width = image.cols;
- height = image.rows;
- }
-
- cv::Mat resizedImage;
- cv::resize(image, resizedImage, cv::Size(width, height), 0, 0, cv::INTER_AREA);
- cv::cvtColor(resizedImage, resizedImage, cv::COLOR_BGR2RGB);
- QImage qImage((const uchar*)resizedImage.data, resizedImage.cols, resizedImage.rows, resizedImage.step, QImage::Format_RGB888);
-
- updateImage(qImage);
- }
- catch(const std::exception& err)
- {
- QuaeroDebug() << err.what();
- }
- }
main函数注册类到qml:
几个关键部分
- QQmlApplicationEngine* engine = new QQmlApplicationEngine();
-
- ptr_paint_image = new PaintItem();
-
- qmlRegisterType
("PaintItem",1,0,"PaintItem"); -
- engine->rootContext()->setContextProperty("paint_image_show",ptr_paint_image);
-
- const QUrl url(QStringLiteral("qrc:/main.qml"));
- QObject::connect(engine, &QQmlApplicationEngine::quit, &app, &QGuiApplication::quit);
-
- engine->load(url);
qml文件中:
第一个坑: 使用方法
注意PaintItem,用他定义的实例ID来显示加载图片。
- import QtQuick 2.15
- import QtQuick.Controls 2.5
- import QtQml.Models 2.15
- import PaintItem 1.0
- import "./ctrl_item"
-
- //省略页面其他,以及定义property int image_index: 1
- Rectangle {
- id: rectangle_opencv_lightimage_show
- border.color: $main_color
- border.width: 2
- anchors.top: parent.top
- anchors.topMargin: 80
- anchors.bottom: parent.bottom
- //anchors.bottomMargin: 20
- anchors.left: parent.left
- width: rectangle_opencv_lightimage_show.height
- color: $main_color
- radius:2
-
- PaintItem {
- id: paintItemDelegate //从这里进行下面的函数操作才可以渲染出图片
- anchors.fill: parent
- }
-
- MultiPointTouchArea {
- id: imagshow_mousearea
- anchors.fill: parent
- onPressed: {
- }
- }
- }//rectangle_opencv_lightimage_show
-
- M_button {
- id: button_last_pic
- anchors.top: rectangle_datahandle .bottom
- anchors.topMargin: 20
- anchors.left: rectangle_datahandle.left
- anchors.leftMargin: 50
- bt_width: 180
- bt_height: 56
- img_source: $icon_base + "insert_up.png"
- bt_txt: qsTr("last_pic")
-
- onClickedLeft: {
- if(image_index === 1)
- image_index = 5;
- else
- image_index --;
- paintItemDelegate.show_image_test(image_index,rectangle_opencv_lightimage_show.width-50,rectangle_opencv_lightimage_show.height-50);
- console.log("image_is:",image_index);
- }
- }
-
- Component.onCompleted: {
- paintItemDelegate.show_image_test(image_index, rectangle_opencv_lightimage_show.width-50, rectangle_opencv_lightimage_show.height-50);
- }
第二个坑:内存溢出:
发生了很奇怪的现象,就是我进入显示页面第一次点击就会跳出,如果退出再进入,就会正常轮流显示,很奇怪。最后解决方法:减小尺寸。如果直接给控件宽度和高度的尺寸,会溢出。必须减去一些值才可以正常显示,我这里给的是-50之后正常显示。
paintItemDelegate.show_image_test(image_index, rectangle_opencv_lightimage_show.width-50, rectangle_opencv_lightimage_show.height-50);
评论记录:
回复评论: