Scaling widget according to screen scaling ratio in OS
-
Hi,
I custom-draw widget using both primitives and text. I defined text size in points and it gets automatically scaled according to OS settings. How can I do the same for primitives so they are scaled proportionally to the text ?Currently I'm testing my code on Windows10. I played with idea of figuring out screen scale using QScreen::logicalDotsPerInch() and QScreen::physicalDotsPerInch() but results are not what I expected.
for 100% scaling Logicalpixel 96 DPI, Physicalpixel 159.856 DPI
for 150% scaling Logicalpixel 144 DPI, Physicalpixel 159.856 DPI
for 200% scaling Logicalpixel 192 DPI, Physicalpixel 159.856 DPIIs assumption correct that scale always equals to QScreen::logicalDotsPerInch()/96 ?
Has anyone played with this on other OSes and can share some experience ?What do you think about using QFontMetrics ? I can draw primitives using size of reference character QFontMetrics::boundingRect(). It works but I'm not sure how reliable this method is...
When scale is changed on the fly I noticed that not everything in Qt apps gets re-scaled properly. I assume that this is still WIP in Qt.
-
@levi.pl said:
Is assumption correct that scale always equals to QScreen::logicalDotsPerInch()/96 ?
Well that is what I use, based on advice from the Qt folks, for widget scaling on Windows, but I've seen a case where a Linux VM running on a Mac with Retina display broke that assumption.
Has anyone played with this on other OSes and can share some experience ?
Mac OSX handles this automatically, except in the case of drawing with OpenGL, in which case scaling by devicePixelRatio() is needed.
Sorry I can't be of more help.
-
Hi and welcome to devnet,
Which version of Qt are you using ?
-
@SGaist
Thank you.I'm using Qt 5.7.0 64bit compiled with MSVC2015. Build downloaded from qt.io.
What I noticed is fonts on standard widgets are scaled properly but widgets themselves do not claim more space to fit them.
This causes fonts to be clipped. I can provide screenshots where you can see the issue on OMenuBar and QGroupbox inside QMainWindow.
I also noticed that QMessageBox does not grow proportionally to the font size. QCombobox does not scale dropdown list font.All this happens when you change scaling factor on the fly. When re-launching application after change everything works fine.
-
@KeithS Thank you for confirming "QScreen::logicalDotsPerInch()/96" . I will use it for now. Dynamic scaling on Xorg/Kde does not work so I can't compare.
Suggestion for Qt folks is to put some guidelines in documentation so people won't have to reinvent the wheel.
-
@SGaist
I did. Thank you. What I'm missing is examples how to use QScreen in practice. I guess I have to download Qt sources to check how it was done for standard widgets.The way I use it now is in custom-drawn-widget class constructor I instantiate QScreen and use calculated scaling ratio to scale all widget's elements and I use signals to redraw widget when scale/dpi/resolution changes. Yet it does not feel right. QScreen should be created for top level widgets and information should be cascaded down to all widgets contained within. That's why I'm seeking advice from professionals :-)
-
AFAIK, you should use QApplication to query the QScreen e.g. the screens method
-
@SGaist
That is good suggestion, thanks.I still have couple doubts:
- How to optimally cascade this information down to all widgets.
- Why some elements (like fonts) rendered by Qt are reacting on scale change on-the-fly
- How standard widgets are aware of scaling factor. There must be something already there - this would save me from pain of implementing point 1
I went back to "High DPI displays" document I found following suggestions which suggest that document may be obsolete ...
*Size windows and dialogs in relation to the screen size.
This is opening doors to hardcore GUI implementation ideology but fine. Still problem of proper sizing of non top level widgets is unresolved by this. Moreover if you only resize window you'll get lots of free space...
*Replace hard-coded sizes in layouts and drawing code by values calculated from font metrics or screen size.
I don't get this one. Drawing code should use screen scale factor and not unreliable font metrics or screen resolution ... If user wants to have interface scaled by two he should get everything twice the normal size.
Do you know how to ask someone from Qt team via forum ?
-
To contact Qt devs directly, you should bring your points to the interest mailing list. You'll find there Qt developers/maintainers. This forum is more user oriented.
-
I figured out some things:
-
You can get logicaldpi from QWidget inherited member functions: QWidget::logicalDpiX() and QWidget::logicalDpiY(). This way your custom drawn widget can be scaled.
-
Fonts are scaled automatically on the fly unless you are using HTML tags. QLabel with plain text will change font size, the one with <font color="red"></font> will not change.
-
Standard widgets either do not update hinted sizes or layout manager is not updated an you need to call update geometry manually.
-
If you want to scale your widget on the fly then you need to create cascade of signal&slot or setter functions from QScreen to your widget (someone, please,prove me wrong :-) )
-
-
Don't forget to update the thread once you get more information :)