On 2020-05-13 23:41, Henry Skoglund wrote:
On 2020-05-13 16:53, Morten Sørvig wrote:
We are indeed planning to addreess high-DPI support for Qt 6. You can
test the implementation on
Qt 5.14+ today by setting
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
This should make sure labels and line edits are correctly sized, also
for 125% and 150%.
Interestingly, Qt will then “lie” about the about the screen size the
same way that dpiawareness=0
does, although while rendering at the full resolution (so no
blurriness).
Morten
Thank you for this!
All of my apps had the blurriness problem, in fact recently one of my
users on a brand new laptop (with a 150% scale screen) complained and
said that my program looked like "East Germany" which (if you're old
enough to realize) is not a compliment :-(
My old code (I wanted a fire-and-forget solution, i.e. no qt.conf
which is easily forgotten, so C++) was this:
...
#if !defined(DPI_AWARENESS_CONTEXT_UNAWARE)
// (these lines are copied from a fresh windef.h)
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
((DPI_AWARENESS_CONTEXT)-2)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
((DPI_AWARENESS_CONTEXT)-3)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
((DPI_AWARENESS_CONTEXT)-4)
#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
((DPI_AWARENESS_CONTEXT)-5)
#endif
static const int nnBuild1703 = 15063; // can use
DPI_AWARENESS_CONTEXT_UNAWARE
static const int nnBuild1809 = 17763; // can use
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
// Windows 10 build 1703 or later?
if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows,10,0,nnBuild1703))
{
// dynamically resolve the address to SetProcessDpiAwarenessContext()
auto f = reinterpret_cast<bool (__stdcall
*)(DPI_AWARENESS_CONTEXT)>(QLibrary("user32.dll").resolve("SetProcessDpiAwarenessContext"));
auto value = DPI_AWARENESS_CONTEXT_UNAWARE;
// on build 1809 (or later)? let's try GDISCALED
if (QOperatingSystemVersion::current() >=
QOperatingSystemVersion(QOperatingSystemVersion::Windows,10,0,nnBuild1809))
value = DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
bool bOk = f(value);
if (!bOk)
qWarning("SetProcessDpiAwarenessContext() failed.");
}
...
I think very few of my users are on Windows 8.1 so I leapfrogged the
DpiAware functions in SHCore.dll and went for the new ones in Windows
10 (they are in user32.dll) but to no avail, it was East Germany
anyway, here are 2 screenshots, first from a 100% screen for
comparison, then from a 125% screen using my code above (I've
anonymized patient names etc.):
https://tripleboot.org/Pictures/Scale100Percent.png
https://tripleboot.org/Pictures/Scale125PercentDpiAwareness0.png
On the 100% screen all is fine and dandy but on the 125% screen ->
fuzziness galore.
So I tossed the code above and tried your 2 liner from today:
...
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
...
Voila: https://tripleboot.org/Pictures/Scale125PercentPassThrough.png
Goodbye East Germany!
Thank you again /Henry
P.S. Now this wouldn't be complete without some small complaint, I'm
thinking of the horizontal lines for separating the different rows of
patients (they are QFrames, or "Horizontal Line" as they are called in
Qt Creator's widget designer).
I insert them manually on top of the QTableWidget, they have a
lineWidth of 1 and are rendered as such on the 100% or the 200%
screens. But on 125%, 150% etc. screens they are rendered a bit uneven
using the new 2 liner/passthrough code, you can see it on my last/3rd
screenshot. I suspect it's some kind of rounding problem. This is
*not* a big deal, just me being pedantic.
About that "rounding problem", don't bother with it, I think I fixed it,
or at least understand it:
turns it occurs on 125% and 175% screens every 4 row, and on a 150%
screen every 2nd row.
So I added this tweaking code (which simulates the rounding error) where
I calculcate the QRect for the QFrame:
...
int top = ...... // the top for the QFrame's geometry for the current row
int nDPRatioPercent = qRound(devicePixelRatioF() * 100); // will be 100,
125, 150 etc.
int topNudged = (((top * nDPRatioPercent) / 100) * 100) / nDPRatioPercent;
...
topNudged will differ with 1 pixel (compared to top) for every 4th row
on 125% and 175% screens, and for every 2nd row on 150% screens, so I
just use topNudged instead of top for QFrame's geometry. With that tweak
I think I have a good result, screenshot here:
https://tripleboot.org/Pictures/Scale125PercentWithNudge.png
Rgrds Henry
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development