Design user interfaces with automatically scaling fontsizes in Qt - c++

Qt 5.7 is claiming to have improved high DPI support. With modern Qt it is possible to create an app starter like:
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
return app.exec();
}
I expect UI to automatically scale when running on high DPI, but the scaling doesn't necessarily work as expected. At least it doesn't scale the UI for me under Linux. What I am seeing is that the layout scales up, but the fonts stay right where they were, at the sizes Qt Creator assigned them in the form layout tool.
If you want a larger size font for some element, and you set it in form Design screen, there seems no way to say "twice as big". Instead it injects a font property with an absolute point size.
It seems to be the same for the QMessageBox static methods too. Display a static QMessageBox, like QMessageBox::info and its text and icon do not get scaled up to compensate for the high dpi.
So exactly what is it you are supposed to do to allow your Qt application, designed in Creator at a standard DPI, to automatically adjust to a high DPI environment, fonts, QMessageBoxes and all.
I've gotten some traction setting the application's style sheet to use larger font for QMessageBox. but it feels ugly, and I'm not sure how to trigger it automatically.
EDIT:
Manually setting the environment variable
declare -x QT_SCALE_FACTOR=2
Does seem to invoke the sort of behavior I am looking for. But how to do it automatically only on High DPI environment, and preferably inside the program itself . ( setenv (3) could work under Linux, I guess )

As of Qt5.11 the following seems to be good enough for my Ubuntu 18.04 laptop with a 4k screen:
Download and install Qt5.11 from official website (not from apt).
Open the ~/.local/share/applications/DigiaQt-qtcreator-community.desktop file.
Change the line Exec=/path/to/Qt/Tools/QtCreator/bin/qtcreator to Exec=env QT_AUTO_SCREEN_SCALE_FACTOR=1 /path/to/Qt/Tools/QtCreator/bin/qtcreator
Restart Qt Creator.

Related

Custom cursor scaling with windows accessibility settings

I have implemented 32x32 custom cursors with bitmaps using the following approach (in Qt 6.1.1):
this->setCursor(QCursor(QBitmap(":/Cursors/arrow_up.bmp"), QBitmap(":/Cursors/arrow_up_mask.bmp"), 3, 0));
The cursors work as expected if the Windows display setting for size of apps and text is set to 100%. However, if the size of apps and text setting is increased, Qt scales up the custom cursors accordingly and they become pixelated (e.g. if 150% is selected, Qt increases the size of the custom cursors by 50%).
Is there a way to prevent Qt from resizing the custom cursors? Alternatively, is there a way to know what the user has selected in Windows for the size of apps and text, so that I can provide cursors at the correct resolution?
Try this :
QCursor cursor = QCursor(QIcon(":/Cursors/arrow_up.bmp").pixmap(32, 32), 0, 0);
this->setCursor(cursor);
means that use QIcon instead of QBitmap and set its size by pixmap(32, 32).
Another things that may help you :
put this line in your main.cpp file :
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
Read this Document . As I understand setting AA_EnableHighDpiScaling flag Enables high-DPI scaling in Qt on supported platforms (see also High DPI Displays). Supported platforms are X11, Windows and Android. Enabling makes Qt scale the main (device independent) coordinate system according to display scale factors provided by the operating system. This corresponds to setting the QT_AUTO_SCREEN​_SCALE_FACTOR environment variable to 1.

Qt Creator Line edit and button size for hi-dpi and low dpi system

I'm have to re-layout a very complicated UI because we've discovered it's essentially unusable on high dpi systems. This is due to the fact that we have used fixed sizes on just about everything in order to get the layout design we want in Qt Creator.
My Question is, how can I size objects (line edits, buttons, spin boxes, etc etc etc) such that they maintain relative sizes to each other to maintain the desired layout?
For example:
This renderd exactly as it looks on a 1080p screen but it's completely unreadable on a windows tablet with a 2736 x 1824 resolution.
So how do I fix this? If I remove the absolute pixel size values, all those buttons and line edits expand horizontally out of control and nearly tripple the width of the widget. Not only is this completely unnecessary for the data they will contain, it ruins the UI.
I have tried layouts. Layouts don't stop these objects from expanding. There appears to be some hidden minimum size that is set arbitrarily far too large for my purposes.
I have looked over the Qt Creator resources I can find. Lots of patting themselves on the back for supporting hi-dpi, nothing about how to design for this to achieve a consistent look across devices with different resolutions.
What version of Qt?
Qt 5.6 introduce High Dpi Support and adjust all the views by the system scale factor. Take a look to the HDPI Displys Documentation. Basically, add this line to your main function before set up your applicatio to enable the automatic scale:
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
......

How to get sharp UI on high dpi with Qt 5.6?

I am developing on a 4k monitor and its a pain...
Finally I managed to set up QtDesigner and then ecountered this issue:
When you use QT_AUTO_SCREEN_SCALE_FACTOR=1 and compile an app with radiobutton and other basic widgets, it looks scaled on a 4k screen.
Otherwise the dimensions of controls are correct and as expected, its just not sharp, but rather pixelated.
I am running on Windows 10 Home 64bit on 4k screen with 200% DPI zoom, using Qt 5.6 RC msvc2015 64bit and tried with achieving the same results using
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
If I use
QGuiApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
the controls are sharp, text size is ok BUT all dimensions are much smaller.
How do I make controls sharp on high DPI screen?
As Qt documentation says:
Use QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors.
QT_SCREEN_SCALE_FACTORS to set per-screen factors.
QT_SCALE_FACTOR to set the application global scale factor.
You can try doing what Qt Creator is doing:
static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO";
if (!qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO)
&& !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
Basically important thing is the last line QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);.
Here is what was working for me. You can set DPIawareness manually by giving a command line option at the instanciation of the QApplication.
The official documentation is here https://doc.qt.io/qt-5/highdpi.html (section DPI awareness).
According to the documentation, you can set the application to DPI Unaware (thus it will automatically scale but display will be blurred), or to System DPI Aware or to Per-Monitor Aware.
Here is a minimal example code for the instanciation of the QApplication to force High DPI, choose other value than 1 (0 or 2) to enable DPIUnaware or Per Monitor DPI Aware:
int main()
{
int argc = 3;
char*argv[] = {(char*)"Appname", (char*)"--platform", (char*)"windows:dpiawareness=1";
(void) new QApplication(argc, argv);
}
With QT_AUTO_SCREEN_SCALE_FACTOR, the point size of the fonts are not changed, they're just scaled up from their original pixels, so they will never be smooth, only more bumpy.
Ref: http://doc.qt.io/qt-5.6/highdpi.html#high-dpi-support-in-qt
"This will not change the size of point sized fonts"
You need to use QT_SCALE_FACTOR instead to rescale your app, not just rescale its pixels.

Qt 5.3 full screen issue

I have a Qt application which runs on Ubuntu 12.04 Server with KDE plasma desktop. If I compile with Qt 4.8 full screen works as expected. With Qt 5.3, the window is getting bigger than the available resolution. If I set the resolution using the following code, it works.
QSize sz(QApplication::desktop()->size());
main_window->setFixedSize(sz.width() + 1, sz.height() + 1);
main_window->showFullScreen();
Is this the proper way to solve this issue?
Thanks in advance.
Qt is quite flexible in application sizing and provides you with a lots of informations (and options).
For what concerns QApplication you can use QDesktopWidget.
QDesktopWidget * screen = QApplication::desktop();
screen->availableGeometry();
As stated in the docs about availableGeometry:
Returns the available geometry of the screen with index screen. What
is available will be subrect of screenGeometry() based on what the
platform decides is available (for example excludes the dock and menu
bar on Mac OS X, or the task bar on Windows). The default screen is
used if screen is -1.
Read the section "Use of the Primary Screen" in QDesktopWidget docs for details about the "default screen" and the general handling of multiple screens. Using these methods you will have full control over the way your application is laid out, even with multiple screens available.
For what concerns QGuiApplication you can use QScreen:
QScreen * screen = QGuiApplication::primaryScreen();
screen->availableGeometry();
Finally, in QML it is possible (and advisable) to use Screen object which provides Screen.desktopAvailableWidth and Screen.desktopAvailableHeight which ensure proper resizing with different versions of Android/iOS.

Qt app works on desktop, but not laptop?

I am writing an OpenGL app using Qt, and it builds and runs fine on my desktop, but when I try running the exact same code on my laptop, it builds but does not output anything? Here is my main.cpp
#include <QtGui/QApplication>
#include <QtOpenGL/QGLWidget>
#include "GLWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
GLWidget window;
window.resize(1050,700);
window.setFixedSize(1050, 700);
window.show();
return app.exec();
}
I do not want the user to be able to resize the window, hence the fixed size. If I set a breakpoint on the last line of main, it never reaches it on my laptop. I have stepped through the code and right after show() is called (which is just an inline function) the debugger finishes with code 0. I checked all the project build and run settings, they are the same on both machines.
My desktop has a 1920x1080 monitor, but my laptop is only 1366x768 could this have anything to do with it? Is there some sort of internal check going on under the hood in Qt that depends on my screens resolution? That is pretty much the only thing I can think of.
I do not want the user to be able to resize the window
May I ask why? May I presume you want the window to be a fixed size, because you want to use OpenGL to generate a image exactly this size? If so, then I must tell you, it will not work that way. OpenGL implementations will only render what will become visible on the screen (pixel ownership test). If parts of the window are not visible (and in your case this will be the case on the laptop) those pixels are simply not rendered. Reading out the framebuffer will leave those pixels undefined.
The proper way to tackle this problem is using either a PBuffer, or a Frame Buffer Object (FBO). FBOs are easier to use, but not as widely supported on Windows (Intel graphics on Windows have rather poor FBO support). FBOs are supported by all Linux OpenGL implementations (Mesa (also does Intel), ATI/AMD and NVidia). There are numerours FBO and PBuffer tutorials in the web.