Qt使用GDI绘图(仅Windows平台)

简介: Qt使用GDI绘图(仅Windows平台)

绘图引擎


Windows环境下二维绘图引擎有多种选择:GDI、GDI+、DirectDraw、Qt/QPainter、Agg、Cairo、skia、Direct2D、Direct3D、OpenGL等。


GDI:微软原生的二维绘图引擎。


优点:微软的全力支持,作为操作系统核心层效率方面不用担心,支持多种开发框架(含语言):WinSDK、MFC、Delphi等。


缺点:不是面向C++对象组织的,使用起来较为繁琐;不支持反锯齿,不支持复杂的绘图效果(这个相对于GDI+而言)。


GDI+:微软后来推出的二维绘图引擎。


优点:微软的全力支持,支持多种开发框架(含语言):WinSDK、MFC、Delphi等,可以实现复杂的绘图效果,如反锯齿、路径画刷等;面向对象的架构,使用起来比较方便。


缺点:绘图效率较GDI稍低,绘图交互性不如GDI(缺少GDI的支持位运算的绘图模式),开启反锯齿后效率不如Qt。如果不考虑绘图的效果,使用Win32 GDI函数直接绘图的效率大约是同样的GDI+的10倍以上。


DirectDraw:从GDI、GDI+到Direct 2D的一个过渡产品,微软已明确表示不推荐使用。


Qt:Qt的二维图形引擎是基于QPainter类的,绘图的效果取决于QPainter的设置。面向对象的方式组织,使用起来较为方便。


Agg:C++编写的开源绘图引擎(基于GPL协议).AGG是C++编写的,因此,它不能被C语言很好地调用。由于其中使用了大量的现代标准C++语言的语法规则,包括模板、仿函数等处理 ,导致这样的库的学习过程将是痛苦的。AGG自从2006年之后就没有更新过。


Cairo:C编写的开源绘图引擎(基于LGPL协议),大名鼎鼎的FireFox就是用这个绘图引擎的。Cairo是非常流行的开源2D图形渲染引擎库,它支持包括X-Windos,Win32,图像,pdf在内的各种输出设备。目前,Cairo已被广泛的使用在多个平台上来渲染图形界面,包括Firefox/Webkit-EFL/GTK+/Poppler/Qt等等。Qt的QPainter提供的抗锯齿效果没有cairo的好,在理想情况下,cairo的用户可以在打印机和屏幕上获得非常接近的输出效果。cairo 是用 C 编写的,但是为大多数常用的语言提供了绑定。选用 C 语言有助于创建新的绑定,同时在进行 C 语言调用时可以提供高性能。应该特别注意 Python 绑定,它支持快速原型开发,而且降低了学习 cairo 绘图 API 的门槛。 Cairo的绘图效率是接近GDI/GDIPlus的。经过优化算法,可以做到完全忽略绘图效率上的差别。此外,gtk不如qt流行,Qt支持cairo。


Skia:Google的Android的绘图引擎。它是一个C++的开源2D向量图形处理函数库,包括字型、坐标转换、位图等等。skia相当于轻量级的Cairo(Cairo是矢量图形库)。


Direct2D:微软在WindowsVista及之后的Windows版本推出的意在取代GDI、GDI+的二维绘图引擎,支持硬件加速。Direct 2D是微软在后XP时代开发的开发二维绘图引擎。微软出于兼容性的考虑还会继续对GDI、GDI+进行支持,但毫无疑问微软的策略是要Direct 2D取代GDI和GDI+的,因此在WindowsVista及其之后的Windows上进行二维绘图开发,建议是直接使用Direct2D。Direct 2D支持硬件加速,在绘图效率应有一定程度的提升。


Direct3D:微软开发的3D绘图引擎。


OpenGL:SGI开发的3D绘图引擎。OpenGL的优势是三维绘图,不建议用来二维绘图,因为OpenGL在二维一些操作并不合适,如二维中的点、线捕捉、自定义图例的添加、打印的支持等等。


更详细的内容请见我的另一篇博文:


https://blog.csdn.net/libaineu2004/article/details/105308235



使用GDI取代QPainter


QPainter在高频绘画的使用CPU占用较高,我们可以使用GDI绘图。由于没有复杂的抗锯齿处理,GDI绘图效率非常不错。GDI因为是使用GPU绘图,会减少CPU占用。

因为Qt是通过repaint和update事件触发paintEvent绘图,其他绘图会被覆盖,所以需要以下方法实现GDI绘图:

在需要绘图的Widget构造函数写setAttribute(Qt::WA_PaintOnScreen, true);

重写该Widget的QPaintEngine * paintEngine()函数返回nullptr;

在绘图函数用GDI绘图,不要在paintEvent实现,因为刷新会慢,在自己主动调用的函数里写:

HWND hwnd;
hwnd = (HWND)this->winId();
HDC labelDC = GetDC(hwnd);//取得窗体句柄
QImage image(imageRaw.get(), m_w, m_h, QImage::Format_Grayscale8);//imageRaw是std::shared_ptr<unsigned char>类型,m_w和m_h是图像宽高
QPixmap pixmap = QPixmap::fromImage(image);
HBITMAP bitMap = toHBITMAP(pixmap);//通过一系列转换得到HBITMAP位图
HDC  hdcsource1 = CreateCompatibleDC(labelDC);//创建后备显示缓冲
SelectObject(hdcsource1, bitMap);
BitBlt(labelDC, 0, 0, m_w, m_h, hdcsource1, 0, 0, SRCCOPY);//将后备缓冲显示到屏幕
ReleaseDC(hwnd, labelDC);
DeleteObject(hdcsource1);
DeleteObject(bitMap);



Qt绘图获取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,推荐使用!




参考文献


https://blog.csdn.net/wwwwxhh/article/details/79461668


https://blog.csdn.net/ssitu/article/details/54615746


相关文章
|
25天前
|
XML C# 数据格式
掌握了在Windows平台上查看DLL依赖的方法
掌握了在Windows平台上查看DLL依赖的方法
170 4
|
2月前
|
监控 Windows
Windows平台RTSP|RTMP播放器如何实时调节音量
我们在做Windows平台RTSP、RTMP播放器的时候,有这样的技术需求,特别是多路监控的时候,并不是每一路audio都需要播放出来的,所以,这时候,需要有针对音量调节的设计
|
3月前
|
容器
【qt】GraphicsView绘图架构
【qt】GraphicsView绘图架构
71 0
|
3月前
【qt】绘图
【qt】绘图
33 0
|
1月前
(14)Qt绘图(one)
本文介绍了在Qt中使用QPainter进行绘图的基础操作,包括如何指定绘图设备、使用QPen和QBrush设置线条和填充样式、绘制不同样式的线条和形状,以及如何实现纹理填充和渐变填充等效果。
57 6
(14)Qt绘图(one)
|
1月前
|
计算机视觉
(15)Qt绘图(two)
Qt框架中QPainter类的多种绘图功能,包括坐标变换、基本图形绘制、文本和图片绘制、图像保存以及碰撞检测等。
41 1
(15)Qt绘图(two)
|
1月前
|
NoSQL Shell MongoDB
Windows 平台安装 MongoDB
10月更文挑战第10天
42 0
Windows 平台安装 MongoDB
|
2月前
|
监控 C# 块存储
Windows平台RTSP|RTMP播放器如何叠加OSD文字
做Windows平台RTSP|RTMP播放器的时候,特别是多路播放场景下,开发者希望可以给每一路RTSP或RTMP流添加个额外的OSD台标,以区分不同的设备信息(比如添加摄像头所在位置),本文主要探讨,如何动态添加OSD台标。
Windows平台RTSP|RTMP播放器如何叠加OSD文字
|
2月前
|
编译器 Windows
plugin cannot be loaded for module “QtQuick“ && Could not load the Qt platform plugin “windows“
本文讨论了在Qt应用程序中遇到的平台插件加载问题,包括具体的错误信息、解决方案和参考链接。问题表现为无法加载“QtQuick”模块的插件,并且无法找到“windows”平台插件。解决方案是修改环境变量`Qt5_DIR`以使用正确的Qt版本和编译器环境。
|
2月前
|
Linux Android开发 iOS开发
Windows平台RTSP|RTMP播放器如何实现实时录像功能
Windows平台RTSP、RTMP播放器实时录像接口设计,实际上,除了Windows平台,我们Linux、Android、iOS平台也是一样的设计,单纯的录像模块,如果做的全面,也不是一两个接口可以搞定的

热门文章

最新文章

推荐镜像

更多