学习Qt使用GDI+绘图笔记
GDI+学习笔记
- 1.GDI+介绍:
- 2.GDI+的载入与卸载:
- 3.Qt中GDI+的使用
- (1).pro文件设置
- (2)widget属性设置
- (3)重载painEngine()方法
- (4)获取HDC
- 4.静态函数FromFile、FromHBitmap和FromStream的使用
- 5.在 Qt 中使用 GDI+ 的实例
- 6.遇到的一些问题:关于Bitmap的复制拷贝,以及多图交互的问题。
借鉴文章:博主「利白」的原创文章
借鉴文章:博主「litanyuan」的原创文章
链接:GDI+ MSDN文档
1.GDI+介绍:
GDI+ 是 Windows 提供的图形设备接口 GDI 的后续版本,相比 GDI ,GDI+ 是面向对象的,使用更方便。
GDI:微软原生的二维绘图引擎
优点: 微软的全力支持,作为操作系统核心层效率方面不用担心,支持多种开发框架(含语言):WinSDK、MFC、Delphi等。
缺点: 不是面向C++对象组织的,使用起来较为繁琐;不支持反锯齿,不支持复杂的绘图效果(这个相对于GDI+而言)。
GDI+:微软后来推出的二维绘图引擎
优点: 微软的全力支持,支持多种开发框架(含语言):WinSDK、MFC、Delphi等,可以实现复杂的绘图效果,如反锯齿、路径画刷等;面向对象的架构,使用起来比较方便。
缺点: 绘图效率较GDI稍低,绘图交互性不如GDI(缺少GDI的支持位运算的绘图模式),开启反锯齿后效率不如Qt。如果不考虑绘图的效果,使用Win32 GDI函数直接绘图的效率大约是同样的GDI+的10倍以上。
关于绘图引擎的更多介绍请看:博主「利白」的原创文章
https://blog.csdn.net/libaineu2004/article/details/105475604
2.GDI+的载入与卸载:
使用 GDI+ 进行绘图,需要引入相关的库文件以及头文件,并且进行 GDI+ 环境的初始化操作。
(1)引入相关头文件(.h)及lib
//#include <stdafx.h> //这个头文件可以不用加
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
(2)GDI+的启动和关闭
在使用 GDI+ 绘图之前需要调用 GdiplusStartup 加载动态链接库 Gdiplus.dll 以对 GDI+进行初始化;在使用绘图结束后需要调用 GdiplusShutdown 卸载动态链接库以对 GDI+ 进行清除工作。
//启动
Gdiplus::GdiplusStartupInput StartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &StartupInput, NULL);//GDI+初始化
//关闭
Gdiplus::GdiplusShutdown(m_gdiplusToken);//GDI+ 清除
(3)使用 RAII 管理 GDI+ 资源
定义一个类 GDIPlusHelper,把GDI+ 的启动和关闭操作分别写入类的构造和析构函数中,用来对 GDI+ 进行初始化和清理工作;然后在需要使用 GDI+ 绘图的 widget 中定义一个 GDIPlusHelper 成员即可。
GDIPlusHelper 类定义如下:
#pragma once
#include <QObject>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "Gdiplus.lib")
using namespace Gdiplus;
class GDIPlusHelper : public QObject
{Q_OBJECTpublic:GDIPlusHelper(QObject *parent = nullptr){Gdiplus::GdiplusStartupInput StartupInput;Gdiplus::GdiplusStartup(&m_gdiplusToken, &StartupInput, NULL);//GDI+初始化}~GDIPlusHelper(){Gdiplus::GdiplusShutdown(m_gdiplusToken);//GDI+ 清除}
private:ULONG_PTRm_gdiplusToken; //GDI+句柄//unsigned long long m_gdiplusToken;
};
一些注意事项:
1.在使用GDI+中相关函数和结构时,尽量加上Gdiplus命名空间名,以防止与其它模块的代码由于字段的名称同样出现冲突。比方,GDI+库中定义GDI+函数运行结果的每句类型Status,定义例如以下所看到的。假设我们须要推断函数是否正确运行,应该将返回值和Gdiplus::Ok,而不是直接和Ok比较,注意这个加上Gdiplus命名空间名的好习惯。
2.必须在窗体中创建一个此类型的对象或new
一个此类型的对象,保证该类的构造函数和析构函数调用,才可使GDI+成功加载。
例如:GDIPlusHelper gidHelper;或者 GIDPlusHelper *gdiHelper = new GDIPlusHelper();
delete gdiHelper;
后续代码中标明!
3.Qt中GDI+的使用
QPainter在高频绘画的使用CPU占用较高,我们可以使用GDI+绘图。由于GDI+是使用GPU绘图,会减少CPU占用,绘图效率非常不错。
因为Qt是通过repaint和update事件触发paintEvent绘图,其他绘图会被覆盖,所以需要以下方法实现GDI+绘图:
(1).pro文件设置
pro或pri文件中增加: LIBS += -lgdi32 -luser32
(2)widget属性设置
在需要绘图的Widget构造函数写
setAttribute(Qt::WA_PaintOnScreen);
(3)重载painEngine()方法
重写该Widget的QPaintEngine * paintEngine()函数返回nullptr;
一些注意事项:
在绘图函数用GDI+绘图,不要在paintEvent实现,因为刷新会慢,在自己主动调用的函数里写
(4)获取HDC
Qt使用GDI绘图关键在于获取HDC,对于Qt5来说,有3种方法:
1、使用gui-private
pro或pri文件中增加: QT += gui-private
#include <qpa/qplatformnativeinterface.h>QPlatformNativeInterface *fooPlatformNativeInterface= QGuiApplication::platformNativeInterface();
QBackingStore *fooBackingStore = this->topLevelWidget()->backingStore();
HDC fooNRFWGetDC = static_cast<HDC>(fooPlatformNativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), fooBackingStore));
这个方法不需要releaseDC。此方法使用了Qt官方不推荐使用的 gui-private,并且在整个窗口绘图,没有限制。
2、强行使用GetDC
pro或pri文件中增加: LIBS += -lgdi32 -luser32
#include <windows.h>
HWND hwnd = (HWND)this->window()->winId();
HDC hdc = GetDC(hwnd);
ReleaseDC(hwnd, dhc);
方法2只适用于顶层窗体。此方法在整个窗口绘图,没有限制。
3、使用QtWin
pro或pri文件中增加 QT += winextras
#include <QtWin>
HDC hdcScreen = GetDC(NULL);
HDC hdc = CreateCompatibleDC(hdcScreen);
HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, rectForMap.width(), rectForMap.height());
SelectObject(hdc, hbm);
QImage img = QtWin::imageFromHBITMAP(hdc, hbm, rectForMap.width(), rectForMap.height());
//释放GDI资源
DeleteObject(hbm);
DeleteDC(hdc);
ReleaseDC(nullptr, hdcScreen);
该方法是Qt5.2后的一种新的使用GDI绘图的方法,在Qt5.2中,新增了命名空间QtWin,推荐使用!
4.静态函数FromFile、FromHBitmap和FromStream的使用
关于这三个静态函数的使用:
CSDN博主「yaowang107」的原创文章
5.在 Qt 中使用 GDI+ 的实例
当做完以上的准备工作之后,就可以开始使用gdi+ 绘图了,在这里使用了第二种GetDC()方式获取HDC(强制获取)。
使用双缓存模式绘图,m_DBuffer 为 Graphics* 类型,作用是将需要的图片现在缓存中绘制。
void QFrameForm::paintEvent(QPaintEvent *event)
{/*** 双缓冲绘制模式:先在Bitmap(缓存)上绘制需要绘制的图画,** 然后将绘制好的Bitmap图像绘制到屏幕上*/Bitmap bmp(m_nWidth,m_nHeight); //创建画布(位图)m_DBuffer = Graphics::FromImage(&bmp); //为m_DBuffer指定画布,m_DBuffer为Graphics* 类型//绘制图像DrawBmp();/*** 在实际dc设备上绘制,两种方式:*///第一种:直接绘制到屏幕上,绘制速度较慢//Graphics graphics(m_hdc); //指定绘图设备为当前屏幕//graphics.DrawImage(&map,m_nWidth,m_nHeight); //将绘制好的bitmap图像画到屏幕上//第二种:使用CachedBitmap类,更加快速的绘制Graphics graphics(m_hdc);CachedBitmap ccbp(&bmp,&graphics); //绑定位图和绘图设备//graphics.Clear(Color::Black); //刷新背景用(colorse色),防止出现重影graphics.DrawCachedBitmap(&ccbp,0,0);
}void QFrameForm::DrawBmp()
{/* 绘制最好在函数中实现*/Pen pen(m_color,1.0); m_DBuffer->DrawLine(&pen,10,10,50,50); //画线m_DBuffer->DrawEllipse(&pen,csPoint.X,csPoint.Y,100,100); //画椭圆 csPoint为获取到的鼠标当前位置
}
6.遇到的一些问题:关于Bitmap的复制拷贝,以及多图交互的问题。
在项目中遇到了一个多图交互的问题,
当存在多图交互时,可能会涉及到Bitmap数据的拷贝与保存
Bitmap的拷贝与保存使用到了LockBits() 函数和 UnLockBits() 函数有以及BitmapData类,
我在项目中还遇到了Bitmap与QPixmap的相互转换问题。
待续。。。
学习Qt使用GDI+绘图笔记相关推荐
- Qt使用GDI绘图(仅Windows平台)
绘图引擎 Windows环境下二维绘图引擎有多种选择:GDI.GDI+.DirectDraw.Qt/QPainter.Agg.Cairo.skia.Direct2D.Direct3D.OpenGL等. ...
- Windows高级工程师:GDI+绘图;基础入门大全
Windows GDI绘图基础知识 一.Windows可以画直线.椭圆线(椭圆圆周上的曲线)和贝塞尔曲线. 7 个画线函式是: (1)画直线 LineTo BOOL LineTo(HDC hdc ...
- GDI+绘图轻松入门[5]-绘图坐标的理解和应用
我们都知道,有大约五种方式可以获得一个坐标位置,他们分别是new point.PointToClient.PointToScreen,Location及控件鼠标事件传递的坐标.为了了解绘图坐标,我们事 ...
- Qt 开发使用VSCode 笔记2
在之前有写过使用VSCode开发QT的笔记 Qt 开发使用VSCode 在以前的基础上继续学习记录写下<Qt 开发使用VSCode 笔记2> 该笔记相比之前的Qt 开发使用VSCode新加 ...
- OriginPro 科研绘图笔记 一
OriginPro 科研绘图笔记 一 一.前言 二.软件准备 三.数据准备工具 四.快捷绘图 五.函数绘图 六.与其他编程语言接口 一.前言 OriginPro是由OriginLab公司开发的专业版科 ...
- windows编程之GDI绘图 -- 实验3-1
windows编程之GDI绘图 – 实验3-1 文章目录 windows编程之GDI绘图 -- 实验3-1 @[toc] 1.实验名称 2.实验目的 3.实验的步骤和方法 4.代码实现 5.思考题 6 ...
- Qt:QChart绘图介绍(主要包含类:QChart,QTableWidget,QGridLayout)
Qt:QChart绘图介绍(主要包含类:QChart,QTableWidget,QGridLayout) 首先点击[打开]摁键,从excel中读入相关数据 之后点击[计算]摁键,将数据进行处理,并将部 ...
- 使用bitblt提高GDI+绘图的效率(转)
最近在做使用GDI+绘制K线界面发现传统的GDI+绘制方式效率比较低,根本无法满足K线界面及时刷新的速度要求. 所以做了个GDI+绘制图形界面的试验,改试验主要在一个600×600的区域内每隔10MS ...
- cimage和gdi绘图效率比较_GDI+和GDI绘图性能对比实验
龙源期刊网 http://www.qikan.com.cn GDI+ 和 GDI 绘图性能对比实验 作者:王克茹 来源:<科技创新与应用> 2013 年第 25 期 摘 要:本文通过完全相 ...
最新文章
- UML 数据建模EA的基本使用——《用例图的使用》
- java如何做全局缓存_传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式...
- 【WebRTC---进阶篇】(一)服务器基础编程
- 使用python实现对于chineseocr的API调用
- 黑马博客——详细步骤(一)路由跳转和抽取公共部分代码
- 555定时器的应用——单稳态触发器
- 科大讯飞 离线语音识别python_使用python语言调用科大讯飞离线语音合成
- WebService
- office 2010 Word,Excel的功能区突然消失了
- 宏基因组公众号4年精华文章目录,收藏贴(2021.1更新)
- JS网页特效实例:让网页前进和后退
- 【服务器数据恢复】某银行服务器磁盘阵列多块硬盘掉线的数据恢复案例
- 前端笔记(03)——一文看懂flex布局
- 图形学笔记(十八)光场、颜色和感知—— 光场相机(全光函数、光线和光场的定义)、可见光谱、谱功率密度、颜色的生物学基础、Tristimulus Theory、同色异谱、加色与减色系统、颜色空间SPD
- 鲤鱼精的Python学习笔记(一)
- Day69(贪心算法)
- JasperReports配置中文字体
- 超级兔子魔法设置正式版
- 湖南“聚才兴湘”2014年春季特大型综合人才招聘会4月12日举行
- Android 点击View实现前后翻转动画