我正在编写一个需要在高 dpi Windows(192dpi 而不是 96dpi)上运行的 Qt 应用程序。
不幸的是,Qt 框架还不支持高 dpi(至少在 Windows 上),所以我的应用程序及其所有元素看起来只有它应有的一半大小。
有什么方法可以强制/模拟 Windows 自动升级此类应用程序?
使用固定坐标和大小的应用程序在高 DPI 分辨率下看起来很小。尽管即使使用布局,也存在一些关于元素和字体大小和边距的问题。幸运的是,自 Qt 5.4 起就支持高 DPI 显示器,因为已经修复了许多高 DPI 问题。
Windows 上的应用程序可以采用以下“DPI Awareness”级别之一(来自 Qt 文档):
- DPI Unaware:此级别已在 Windows-Vista 中引入。Windows 将假装应用程序在 1920x1080 的 96 DPI 标准显示器上运行,并相应地缩放应用程序。它旨在适应为低 DPI 显示器设计的旧应用程序。这种类型的缩放可能会导致一些伪影。
- System-DPI Aware:此级别已在 Windows-Vista 中引入。仅当连接了多个监视器时,它才与 Per-Monitor DPI Aware 不同。Windows 将计算适用于所有连接的监视器的缩放比例。
- Per-Monitor DPI Aware:此级别已在 Windows 8.1 中引入。Windows 根本不执行任何缩放。
它还指出:
默认情况下,Qt 应用程序是 Windows 8.1 上的 Per-Monitor DPI Aware 或旧版本 Windows 上的 System-DPI Aware。从 Qt 5.4 开始,可以通过将参数传递给平台插件来指定级别(请参阅使用 qt.conf):
<application> -platform windows:dpiawareness=0,1,2
您可以在此处阅读更多信息。
一般来说,要在高 DPI 显示器上拥有良好的 UI,请考虑以下几点:
Qt::AA_UseHighDpiPixmaps
如果您使用像素图,请设置属性QPainter
,或者在特殊情况下计算缩放比例以调整某些元素大小。从 Qt 5.6 开始,Qt 通过属性或环境变量完全支持高 DPI 监视器(在 OS X 上除外,其中支持是本机的)。对于属性方法,使用:
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
QApplication app(argc, argv);
return app.exec();
}
或者设置系统环境变量:
QT_AUTO_SCREEN_SCALE_FACTOR=1
我已经在 Windows 10 上使用高 DPI Surfacebook 监视器测试了这两种方法,结果按预期正确缩放。
这是在 Windows 上解决问题的最快方法。
在可执行文件旁边,创建一个 qt.conf 文件(如果还没有)并添加以下内容:
[Platforms]
WindowsArguments = dpiawareness=0
放大时窗口会显得模糊。此解决方案的最大优势在于 Windows 进行缩放,而不是 Qt。因此,伪影的出现被最小化。此外,这可以应用于已经分发的应用程序,因为它不需要重建。
当然,这不是最令人愉快的结果,而是让您在短期内摆脱困境的最快结果,让您毫无压力地开发“真正的”DPI-aware 版本。
我正在使用 Qt 4.8。首先,您应该使用布局。我的目标是防止用户也调整对话框、表单等的大小。
通过将此代码放入对话框构造函数中,我在不同的 DPI 上实现了正确的显示结果:
adjustSize();
setFixedSize(size());
第一行adjustSize()
调整对话框的大小以适应其内容。第二行在setFixedSize(size())
将对话框的大小调整为内容后修复了对话框的大小,并防止用户调整它的大小。您无需设置尺寸政策。
我正在使用 Qt 4.8.7。这是我的代码。
static float dpiX = (float)0;
inline int autoDpiSize(int inSize)
{
if (dpiX == (float)0)
{
HDC screen = GetDC(0);
dpiX = static_cast<float >(GetDeviceCaps(screen, LOGPIXELSX)) / 96.0;
ReleaseDC(0, screen);
}
return dpiX * inSize;
}
someWidget->setFixedHeight(autoDpiSize(30));