在高dpi Windows平台上自动重新缩放应用程序?

时间:2014-06-23 13:35:28

标签: windows qt hdpi rescale highdpi

我正在编写一个需要在高dpi Windows(192dpi而不是96dpi)上运行的Qt应用程序。

不幸的是Qt框架还没有支持high-dpi(至少在Windows上),所以我的应用程序及其所有元素看起来应该是它应该的一半。

有没有办法强制/模拟Windows自动升级此类应用程序?

5 个答案:

答案 0 :(得分:8)

使用固定坐标和大小的应用程序在高DPI分辨率下看起来很小。虽然即使使用布局,但在元素和字体大小和边距方面存在一些问题。幸运的是,从Qt 5.4开始支持高DPI显示,因为有很多high-DPI issue fixes

Windows上的应用程序可以采用以下级别的“DPI Awareness”(来自Qt文档):

  
      
  • DPI Unaware:此级别已在Windows-Vista中引入。 Windows将假装它正在运行的应用程序   标准显示96 DPI的1920x1080并缩放应用程序   因此。它旨在适应设计的旧应用程序   用于低DPI显示。一些工件可能是由这种类型造成的   缩放。
  •   
  • System-DPI Aware:此级别已在Windows-Vista中引入。它与Per-Monitor DPI Aware的区别仅在于多个监视器   连接的。 Windows将计算适合所有连接的缩放   监视器。
  •   
  • Per-Monitor DPI Aware:此级别已在Windows 8.1中引入。 Windows根本不执行任何扩展。
  •   

它还声明:

  

默认情况下,Qt应用程序是Windows 8.1或Windows上的Per-Monitor DPI Aware   System-DPI意识到旧版本的Windows。截至Qt 5.4,该级别   可以通过将参数传递给平台插件来指定(请参阅   使用qt.conf):

<application> -platform windows:dpiawareness=0,1,2

您可以阅读更多信息here

通常,要在高DPI显示器上拥有良好的UI,请考虑以下事项:

  • 使用最新版本的Qt
  • 使用布局并避免固定大小(除非您自己计算缩放比例)
  • 根据您的应用需求进行适当的DPI相关设置,例如,如果使用Qt::AA_UseHighDpiPixmaps和pixmaps,则设置QPainter属性,或者计算在特殊情况下调整某些元素大小的缩放比例。

答案 1 :(得分:7)

Qt完全支持Qt 5.6以后的高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

我已经使用高DPI表面监视器在Windows 10上测试了这两种方法,结果按预期正确缩放。

答案 2 :(得分:3)

这是在Windows上解决问题的最快捷方式。

在可执行文件旁边,创建一个qt.conf文件(如果尚未存在)并添加以下内容:

[Platforms]
WindowsArguments = dpiawareness=0

放大时窗口会显得模糊。这个解决方案的最大优点是Windows可以进行扩展,而不是Qt。因此,伪影的出现被最小化。此外,这可以应用于已经分发的应用程序,因为它不需要重建。

当然,这不是最令人愉快的结果,但最快可以让您在短期内摆脱困境,让您在没有压力的情况下开发出“真正的”DPI感知版本。

答案 3 :(得分:1)

我正在使用Qt 4.8。首先,您应该使用布局。我的目标是阻止用户调整对话框,表单等的大小。

通过将此代码放在对话框构造函数中,我在不同的DPI上获得了正确的显示结果:

adjustSize();
setFixedSize(size());

第一行adjustSize()调整对话框的大小以适合其内容。 第二行setFixedSize(size())在将内容大小调整为内容后修复了对话框的大小,并阻止用户调整大小。您无需设置大小政策。

答案 4 :(得分:0)

我正在使用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));