Qt图标显示模糊原因及解决方法

自使用Qt以来其实一直都存在这个问题没能解决(Ps: 期间尝试N个版本), 要问为什么我能忍到现在, 主要还是找到一个临时的解决方案, 通过Qss来设置图标就不会出现失真的情况, 还有一种方案就是使用svg格式的图片, 也能解决部分问题
但是这两种方法在设置QLineEditicon的时候无效了.
没办法继续找答案, 灵光一闪间, 想起了iOS开发中有@2x@3x的图片, 用来适配不同屏幕分辨率, 于是搜索qt mac 图片 两倍大小, 真就被我找到答案了, 果然之前还是没有找到正确的搜索姿势o(╯□╰)o

原因

The key to the OS X high-dpi mode is that most geometry that was previously specified in device pixels are now in device-independent points. This includes desktop geometry (which on the 15 inch retina MacBook Pro is 1440×900 and not the full 2880×1800), window geometry and event coordinates. The CoreGraphics paint engine is aware of the full resolution and will produce output at that resolution. For example, a 100×100 window occupies the same area on screen on a normal and high-dpi screen (everything else being equal). On the high-dpi screen the window’s backing store contains 200×200 pixels.

The main benefits of this mode is backwards compatibility and free high-dpi vector graphics. Unaware applications simply continue to work with the same geometry as before and can keep hardcoded pixel values. At the same time they get crisp vector graphics such as text for free. Raster graphics does not get an automatic improvement but is manageable. The downside is the inevitable coordinate system confusion when working with code that mixes points and pixels.

The scale factor between points and pixels is always 2x. This is also true when changing the screen resolution – points and pixels are scaled by the same amount. When scaling for “More Space” applications will render to a large backing store which is then scaled down to the physical screen resolution.

不知道怎么翻译o(╯□╰)o, 大概意思就是OS X采用的是retina屏幕, 这种屏幕在相同尺寸的情况下的一个像素点是之前屏幕的两倍, 也就是DPI更高
Qt默认并不支持这种处理方式, 所以导致实际有一个像素点对应屏幕上两个像素点, 这也就是失真的原因了

原文地址: http://blog.qt.io/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/

解决方法

使用QPainter手动设置绘制大小, 如下代码的图片绘制已经被修改成了可以在高DPI系统中返回一个更大的像素映射, 但是这种行为会破坏现有的代码结构, 代码来控制最好的情况应该是Qt框架来直接控制

1
2
3
4
QRect destinationRect = ...
QIcon icon = ...
painter.drawPixmap(destinationRect, icon.pixmap(destinationRect.size()));
QIcon::pixmap()

所以Qt使用AA_UseHighDpiPixmaps这个应用程序属性来控制渲染:

1
2
// 在Qt 5.1和之后的版本中这个属性默认值是关闭的, 需要手动开启
qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);

一些奇怪的地方

当没有开启搞质量DPI时:
经过尝试, 使用svg矢量图来显示icon一切正常, 单是设置QPushButtonicon时无效, 设置QTreeViewItemicon是正常的
还有就是貌似使用QSS设置icon也不会出现这个bug, 但是不是绝对的, 设置QLineEditicon的时候还是会模糊