Qt5之前,Qt写出来的程序是完全不支持高DPI自适应的,无论DPI多少,都是按照死板的像素值绘制控件等。从Qt5开始,Qt开始支持了高DPI,但效果不算太好——默认只支持整数倍缩放,且如果强制使用小数倍缩放,会出现一些奇怪的问题,比如控件边界不清楚、失真等问题。
我尝试装过Qt5,但由于静态编译出了些问题,只得又退回Qt4.8。在各个论坛询问如何适应高DPI环境,没有任何一个回答是能满足我的要求的,或许Qt本身就有局限性。几天后,我心中出现了一个想法。按照系统DPI设置,重新调整控件的大小,不就行了吗?
说干就干,按照这个思路,写了一段代码,测试效果还不错,贴在这里,大家若有需要可以测试效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| qreal factor = logicalDpiX() / (96.0 * 1.25); if (factor != 1.0) { resize(width()*factor, height()*factor); QList<QWidget*> allControls = findChildren<QWidget*>(); QWidget *wid; QString qss; for (int i=0; i<allControls.size(); i++) { wid = allControls[i]; wid->move(wid->x()*factor, wid->y()*factor); wid->resize(wid->width()*factor, wid->height()*factor); qss = wid->styleSheet(); if (qss.length() > 0) { int p, s = 0; QChar c; QString snum; while ((p = qss.indexOf("px", s, Qt::CaseInsensitive)) != -1) { snum.clear(); s = p + 2; while ((c=qss[--p]).isDigit()) snum = c + snum; p = (int)(snum.toInt()*factor); if (p > 0) qss.replace(snum + "px", QString::number(p)); } wid->setStyleSheet(qss); } } QSize siz; QList<QAbstractButton*> allBtns = findChildren<QAbstractButton*>(); for (int j=0; j<allBtns.size(); j++) { siz = allBtns[j]->iconSize(); siz *= factor; allBtns[j]->setIconSize(siz); } }
|
得将第一行的1.25改成你用来设计UI的显示器的缩放系数。我用笔记本设计UI,缩放系数是125%,所以我写1.25。大部分台式机显示器都是100%。修改完后,把这段代码贴在主窗口的初始化函数中即可。
测试项目图片在下面。可以看出,在高DPI显示器中,程序自适应高DPI(左)和强制使用系统缩放(右)两种方式下,窗口、控件的大小基本相同,而且自适应的更加清晰。
参考: