背景
- 在不同的分辨率和缩放比例下,对客户端的UI进行适配
- 使用qt版本5.15.3
- 使用qt画板.ui进行界面布局
适配方案
方案1
交由Windows进行处理
创建 qt.conf 文件,并添加到 .qrc 资源文件中
qt.conf 文件内容
[Platforms]
WindowsArguments = dpiawareness=0
方案2
由qt进行接管
需要5.14之后才支持
QCoreApplication::SetAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::SetAttribute(Qt::AA_UseHighDpiPixmaps);
会进行四舍五入,整数倍缩放。即
100% <= scale < 150% 按 100% 缩放
150% <= scale < 250% 按 200% 缩放
以此类推...
未能符合实际想要的根据屏幕设置的实际 scale 等比缩放
原因:存在默认的缩放策略 round 会对比例进行四舍五入
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy:Round);
HighDpiScaleFactorRoundingPolicy 的枚举下有多中策略可以选择,其中 PassThrough 是根据实际屏幕设置的 scale 值进行等比缩放
注意点
- 上述高分屏适配代码需要添加到应用初始化之前
int main(int argc, char *argv[]) {
// 高分屏适配
...
QApplication application();
...
}
开发中遇到的问题和解决办法
修改桌面分辨率之后,不能同步刷新应用
解决方案:在所有屏幕添加DPI变动的信号槽
// 获取所有屏幕
QList<QScreen *> screens = QApplication::screens();
// 遍历屏幕对象添加信号槽
...
connect(screen, &QScreen::logicalDotsPerInchChanged, this, &MainWindow::OnLogicalDotsPerInchChanged);
...
// 槽函数实现
void MainWindow::OnLogicalDotsPerInchChanged(qreal dpi)
{
// 获取当前应用位置
QPoint point = QPoint(this->screen()->geometry().x(), this->screen()->geometry().x());
// 遍历screen,获取应用所在位置screen进行应用刷新
for (auto &screen : QApplication::screens()) {
if (QApplication::screenAt(point)->name() == screen->name()) {
update();
}
}
}
多个不同dpi的屏幕之间来回拖动,超过边界时,可能会出现异常放大
系统进行了DWM虚拟化处理,可能出现计算错误的情况
解决方案:在 QApplication 初始化之前调用 windows 函数
SetProcessDPIAware();
参考Windows文档
setProcessDPIAware 函数 (winuser.h) - Win32 apps | Microsoft Learn
遗留问题
屏幕缩放比例在放大时,如何实现应用缩放比例最大值的限制? 例如电脑屏幕缩放比例300%时,限制应用比例为250%