I have read the official Qt documentation and many articles and questions on StackOverflow about high DPI support in Qt. All of them focus on porting old applications and making them work with as least changes as possible.
But if I were to start a brand new application, with the intention to support per-monitor DPI aware app, what is the best approach?
If I understand correctly, Qt::AA_EnableHighDpiScaling
is the very opposite of what I want. I should actually disable HighDpiScaling and calculate all the dimensions manually on runtime?
Many of the suggestions say not to use sizes at all, to use floating layouts. But in many cases at least minimum width and/or minimum height is desired to be present. As Qt Designer only allows me to put values in absolute pixels, what is the right approach? Where should I place the code to recalculate dimensions if monitor resolution changes?
Or should I just go with the automatic scaling?
My solution from previous Qt app (not well tested)
In one of my older apps where I tried to add HighDPI support, I used this approach - list all children of DOM and resize them one by one given some ratio. Ratio = 1 would produce dimensions equal to the ones I specified in Qt Designer.
void resizeWidgets(MyApp & qw, qreal mratio)
{
// ratio to calculate correct sizing
qreal mratio_bak = mratio;
if(MyApp::m_ratio != 0)
mratio /= MyApp::m_ratio;
// this all was done so that if its called 2 times with ratio = 2, total is not 4 but still just 2 (ratio is absolute)
MyApp::m_ratio = mratio_bak;
QLayout * ql = qw.layout();
if (ql == NULL)
return;
QWidget * pw = ql->parentWidget();
if (pw == NULL)
return;
QList<QLayout *> layouts;
foreach(QWidget *w, pw->findChildren<QWidget*>())
{
QRect g = w->geometry();
w->setMinimumSize(w->minimumWidth() * mratio, w->minimumHeight() * mratio);
w->setMaximumSize(w->maximumWidth() * mratio, w->maximumHeight() * mratio);
w->resize(w->width() * mratio, w->height() * mratio);
w->move(QPoint(g.x() * mratio, g.y() * mratio));
}
foreach(QLayout *l, pw->findChildren<QLayout*>())
{
if(l != NULL && !(l->objectName().isEmpty()))
layouts.append(l);
}
foreach(QLayout *l, layouts) {
QMargins m = l->contentsMargins();
m.setBottom(m.bottom() * mratio);
m.setTop(m.top() * mratio);
m.setLeft(m.left() * mratio);
m.setRight(m.right() * mratio);
l->setContentsMargins(m);
l->setSpacing(l->spacing() * mratio);
if (l->inherits("QGridLayout")) {
QGridLayout* gl = ((QGridLayout*)l);
gl->setHorizontalSpacing(gl->horizontalSpacing() * mratio);
gl->setVerticalSpacing(gl->verticalSpacing() * mratio);
}
}
QMargins m = qw.contentsMargins();
m.setBottom(m.bottom() * mratio);
m.setTop(m.top() * mratio);
m.setLeft(m.left() * mratio);
m.setRight(m.right() * mratio);
// resize accordingly main window
qw.resize(qw.width() * mratio, qw.height() * mratio);
qw.setContentsMargins(m);
qw.adjustSize();
}
which is called from main:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyApp w;
// gets DPI
qreal dpi = a.primaryScreen()->logicalDotsPerInch();
MyApp::resizeWidgets(w, dpi / MyApp::refDpi);
w.show();
return a.exec();
}
I don't consider this a good solution. Given that I am starting fresh and I can fully customise my code to the latest Qt standards, what approach should I use to get HighDPI apps?