【QML】用 Image(QQuickPaintedItem) 显示图片

2024-06-24 06:28

本文主要是介绍【QML】用 Image(QQuickPaintedItem) 显示图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 大体功能:
  • 频繁地往界面推送图片,帧率达到视频效果。
  • 捕获画布上的鼠标事件和键盘事件。
  1. 代码如下:
// DrawImageInQQuickPaintedItem.pro 代码如下:
QT += quick# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \drawimagectrl.cpp \imagepainter.cpp \main.cppRESOURCES += qml.qrc# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetHEADERS += \drawimagectrl.h \imagepainter.hLIBS += -lopencv_core \-lopencv_imgcodecs// imagepainter.h 代码如下:
#ifndef IMAGEPAINTER_H
#define IMAGEPAINTER_H#include <QQuickPaintedItem>
#include <QImage>#define QML_WRITABLE_PROPERTY(type, name) \protected: \Q_PROPERTY (type name READ get_##name WRITE set_##name NOTIFY name##Changed) \type m_##name; \public: \type get_##name () const { \return m_##name ; \} \public Q_SLOTS: \bool set_##name (type name) { \bool ret = false; \if ((ret = m_##name != name)) { \m_##name = name; \emit name##Changed (m_##name); \} \return ret; \} \Q_SIGNALS: \void name##Changed (type name); \private:class MyQImage : public QObject
{Q_OBJECT
public:explicit MyQImage(QObject *parent = nullptr) : QObject(parent) {}~MyQImage() = default;void setImage(const QImage &img) { m_img = img; }const QImage &getImage() const { return m_img; }private:QImage m_img;
};class ImagePainter : public QQuickPaintedItem
{Q_OBJECTQML_WRITABLE_PROPERTY(MyQImage*, pImage)QML_WRITABLE_PROPERTY(int, nFillMode)public:explicit ImagePainter(QQuickItem *parent = nullptr);void paint(QPainter *painter) override;
};#endif // IMAGEPAINTER_H// imagepainter.cpp 代码如下:
#include "imagepainter.h"
#include <QPainter>ImagePainter::ImagePainter(QQuickItem *parent): QQuickPaintedItem(parent), m_pImage(nullptr), m_nFillMode(0)
{connect(this, &ImagePainter::pImageChanged,[this]{if(m_pImage) {setImplicitWidth(m_pImage->getImage().width());setImplicitHeight(m_pImage->getImage().height());}else {setImplicitWidth(0);setImplicitHeight(0);}update();});
}void ImagePainter::paint(QPainter *painter)
{if(m_pImage) {const QImage &image = m_pImage->getImage();if (image.isNull()) {return;}switch (m_nFillMode) {case 1 /* PreserveAspectFit */: {QImage scaledImage = image.scaled(width(), height(), Qt::KeepAspectRatio);double x = (width() - scaledImage.width()) / 2;double y = (height() - scaledImage.height()) / 2;painter->drawImage(QPoint(x, y), scaledImage);break;}case 0 /* Stretch */:default: {painter->drawImage(QPoint(0, 0), image.scaled(width(), height()));}}}
}// drawimagectrl.h 代码如下:
#ifndef DRAWIMAGECTRL_H
#define DRAWIMAGECTRL_H#include <QObject>
#include "opencv2/opencv.hpp"
#include "imagepainter.h"#define SINGLETON(x)     \
private: \x(x const&); \void operator=(x const&); \
public: \
static x* getInstance(QObject *parent = 0) \
{ \static bool first=true; \if ((parent == 0) && (first == true)) { qCritical("Incorrect Initialisation - no parent and first"); } \if ((parent != 0) && (first == false)) { qCritical("Incorrect Initialisation - parent and not first"); } \first = false; \static x *instance = new x(parent); \return instance; \
} \
private:#define QML_CONSTANT_PROPERTY(type, name) \protected: \Q_PROPERTY (type name READ get_##name CONSTANT) \type m_##name; \public: \type get_##name () const { \return m_##name ; \} \private:class DrawImageCtrl : public QObject
{Q_OBJECTSINGLETON(DrawImageCtrl)QML_CONSTANT_PROPERTY(MyQImage*, pSceneImage)public:explicit DrawImageCtrl(QObject *parent = nullptr);~DrawImageCtrl();public slots:void sltTestDrawImage();// 辅助事件void sltWindowWidthChanged(qreal lfWindowWidth);void sltWindowHeightChanged(qreal lfWindowHeight);// 鼠标事件void sltMousePressed(qreal lfX, qreal lfY, quint32 nButtonValue);void sltMouseReleased(qreal lfX, qreal lfY, quint32 nButtonValue);// 键盘事件void sltKeyPressed(int nKey);void sltKeyReleased(int nKey);signals:void sigImageUpdate();private:void showImage(const cv::Mat &mat);private:// 界面属性qreal m_lfWindowWidth;qreal m_lfWindowHeight;double m_lfLastMouseX;double m_lfLastMouseY;// 快照属性double m_lfZoomFactor;double m_lfImgX;double m_lfImgY;
};#endif // DRAWIMAGECTRL_H// drawimagectrl.cpp 代码如下:
#include "drawimagectrl.h"
#include <QTimer>
#include <QDebug>DrawImageCtrl::DrawImageCtrl(QObject *parent): QObject(parent), m_pSceneImage(new MyQImage(this)), m_lfWindowWidth(0.0), m_lfWindowHeight(0.0), m_lfLastMouseX(-1), m_lfLastMouseY(-1), m_lfZoomFactor(1.0), m_lfImgX(0.0), m_lfImgY(0.0)
{}DrawImageCtrl::~DrawImageCtrl()
{if(nullptr != m_pSceneImage){delete m_pSceneImage;m_pSceneImage = nullptr;}
}void DrawImageCtrl::sltTestDrawImage()
{static int i = 0;QString sPicFileName = QString::fromUtf8("/home/xiaohuamao/mycode/DrawImageInQQuickPaintedItem/TestPic/%1.png").arg(i);if(++i >= 100)i = 0;cv::Mat image = cv::imread(sPicFileName.toStdString());showImage(image);QTimer::singleShot(10, this, &DrawImageCtrl::sltTestDrawImage);
}void DrawImageCtrl::sltWindowWidthChanged(qreal lfWindowWidth)
{m_lfWindowWidth = lfWindowWidth;
}void DrawImageCtrl::sltWindowHeightChanged(qreal lfWindowHeight)
{m_lfWindowHeight = lfWindowHeight;
}void DrawImageCtrl::sltMousePressed(qreal lfX, qreal lfY, quint32 nButtonValue)
{qDebug() << QString::fromUtf8("sltMousePressed x:%1,y:%2,btn:%3").arg(lfX).arg(lfY).arg(nButtonValue);
}void DrawImageCtrl::sltMouseReleased(qreal lfX, qreal lfY, quint32 nButtonValue)
{qDebug() << QString::fromUtf8("sltMouseReleased x:%1,y:%2,btn:%3").arg(lfX).arg(lfY).arg(nButtonValue);
}void DrawImageCtrl::sltKeyPressed(int nKey)
{qDebug() << QString::fromUtf8("sltKeyPressed nKey:%1").arg(nKey);
}void DrawImageCtrl::sltKeyReleased(int nKey)
{qDebug() << QString::fromUtf8("sltKeyReleased nKey:%1").arg(nKey);
}QImage cvMatToQImage( const cv::Mat &inMat )
{switch ( inMat.type() ){// 8-bit, 4 channelcase CV_8UC4:{QImage image( inMat.data,inMat.cols, inMat.rows,static_cast<int>(inMat.step),QImage::Format_ARGB32 );return image;}// 8-bit, 3 channelcase CV_8UC3:{QImage image( inMat.data,inMat.cols, inMat.rows,static_cast<int>(inMat.step),QImage::Format_RGB888 );return image.rgbSwapped();}// 8-bit, 1 channelcase CV_8UC1:{
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)QImage image( inMat.data,inMat.cols, inMat.rows,static_cast<int>(inMat.step),QImage::Format_Grayscale8 );
#elsestatic QVector<QRgb>  sColorTable;// only create our color table the first timeif ( sColorTable.isEmpty() ){sColorTable.resize( 256 );for ( int i = 0; i < 256; ++i ){sColorTable[i] = qRgb( i, i, i );}}QImage image( inMat.data,inMat.cols, inMat.rows,static_cast<int>(inMat.step),QImage::Format_Indexed8 );image.setColorTable( sColorTable );
#endifreturn image;}default:qWarning() << "cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();break;}return QImage();
}void DrawImageCtrl::showImage(const cv::Mat &mat)
{cv::Mat image = mat.clone();m_pSceneImage->setImage(cvMatToQImage(mat));auto lfAspectRatio = 1. * image.cols / image.rows;auto lfAspectRatio2 = 1. * m_lfWindowWidth / m_lfWindowHeight;auto lfFactor = 1.0;if (lfAspectRatio > lfAspectRatio2)lfFactor = 1. * m_lfWindowWidth / image.cols;elselfFactor = 1. * m_lfWindowHeight / image.rows;double lfImgX = (m_lfWindowWidth / lfFactor - image.cols) / 2;double lfImgY = (m_lfWindowHeight / lfFactor - image.rows) / 2;emit sigImageUpdate();m_lfZoomFactor = lfFactor;m_lfImgX = lfImgX;m_lfImgY = lfImgY;
}// main.cpp 代码如下:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "drawimagectrl.h"
#include "imagepainter.h"void initDrawImage(QQmlApplicationEngine &engine)
{qmlRegisterType<ImagePainter>("MyItem", 1, 0, "ImagePainter");engine.rootContext()->setContextProperty(QLatin1String("drawImageCtrl"), DrawImageCtrl::getInstance());
}int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQGuiApplication app(argc, argv);QQmlApplicationEngine engine;const QUrl url(QStringLiteral("qrc:/main.qml"));QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection);initDrawImage(engine);engine.load(url);return app.exec();
}// main.qml 代码如下:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")DrawImage {anchors.fill: parent}Button {text: "draw"onClicked: {drawImageCtrl.sltTestDrawImage();}}
}// DrawImage.qml 代码如下:
import QtQuick 2.0
import MyItem 1.0Rectangle {id : canvasRectConnections{target: drawImageCtrlfunction onSigImageUpdate(){idSceneImage.update();}}Image {id: imgCanvaswidth: parent.widthheight: parent.heightanchors.fill: parentImagePainter {id: idSceneImageanchors.fill: parentnFillMode: Image.PreserveAspectFitpImage: drawImageCtrl.pSceneImagevisible: true}MouseArea {anchors.fill: parenthoverEnabled: truepropagateComposedEvents: trueacceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MidButtononEntered: {imgCanvas.forceActiveFocus();}onPressed: {drawImageCtrl.sltMousePressed(mouse.x, mouse.y, mouse.button);}onReleased: {drawImageCtrl.sltMouseReleased(mouse.x, mouse.y, mouse.button);}}Keys.onPressed: {drawImageCtrl.sltKeyPressed(event.key);}Keys.onReleased: {drawImageCtrl.sltKeyReleased(event.key);}onWidthChanged: {drawImageCtrl.sltWindowWidthChanged(imgCanvas.width);}onHeightChanged: {drawImageCtrl.sltWindowHeightChanged(imgCanvas.height);}}onVisibleChanged: {if(canvasRect.visible) {imgCanvas.focus = true;}else {imgCanvas.focus = false;}}onFocusChanged: {if(canvasRect.focus)imgCanvas.focus = true;}
}

这篇关于【QML】用 Image(QQuickPaintedItem) 显示图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089415

相关文章

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

基于Python实现高效PPT转图片工具

《基于Python实现高效PPT转图片工具》在日常工作中,PPT是我们常用的演示工具,但有时候我们需要将PPT的内容提取为图片格式以便于展示或保存,所以本文将用Python实现PPT转PNG工具,希望... 目录1. 概述2. 功能使用2.1 安装依赖2.2 使用步骤2.3 代码实现2.4 GUI界面3.效

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图