Development/Tutorials/Graphics/HiDPI: Difference between revisions

From KDE TechBase
(→‎QPainter: QPolygon to QPolygonF)
(5 intermediate revisions by the same user not shown)
Line 21: Line 21:
In your application's main function, add the following lines at the very beginning:
In your application's main function, add the following lines at the very beginning:


<SyntaxHighlight lang="cpp">
<SyntaxHighlight lang="cpp" highlight="4">
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
{
     QApplication app(argc, argv);
     QApplication app(argc, argv);
     app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
     QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
     ...
     ...
}
}
Line 47: Line 47:
</SyntaxHighlight>
</SyntaxHighlight>


So where is the <code>dpr</code> variable from? You can get it from any <code>QWidget</code> objects with function <code>devicePixelRatioF()</code>. '''F''' means the function return a float number (<code>qreal</code>).
So where is the <code>dpr</code> variable from? You can get it from any <code>QWidget</code> objects with function <code>devicePixelRatioF()</code>. '''F''' means the function return a float number (<code>qreal</code>). If you are not in a <code>QWidget</code> class context, you can get the value via:
 
<SyntaxHighlight lang="cpp">
const qreal dpr = qApp->devicePixelRatio();
</SyntaxHighlight>


And don't forget to change <code>width</code> and <code>height</code> from <code>int</code> to <code>qreal</code>.
And don't forget to change <code>width</code> and <code>height</code> from <code>int</code> to <code>qreal</code>.
Line 53: Line 57:
== QPainter ==
== QPainter ==


<code>QRect</code>, <code>QPolygon</code> and <code>QPoint</code> process all dimensions as integers. You need to change all of them to <code>QRectF</code>, <code>QPolygonF</code> and <code>QPointF</code>.
<code>QPainter</code> has various drawing functions. You need to change parameters of those functions from integer types:
 
* <code>QRect</code>
* <code>QPolygon</code>
* <code>QPoint</code>
* <code>int</code>
 
to floating types:
 
* <code>QRectF</code>
* <code>QPolygonF</code>
* <code>QPointF</code>
* <code>qreal</code>


All width and height variables have to be <code>qreal</code> type instead of <code>int</code>.
For example, you need to change this code:
 
<SyntaxHighlight lang="c++">
QPainter p;
p->drawText(0, 0, 12, 50, Qt::AlignLeft | Qt::AlignTop, text);
</SyntaxHighlight>
 
to:
 
<SyntaxHighlight lang="c++">
QPainter p;
p->drawText(QRectF(0, 0, 12, 50), Qt::AlignLeft | Qt::AlignTop, text);
</SyntaxHighlight>


After all these changes, your <code>QPainter</code> object should be able to render HiDPI graphics.
After all these changes, your <code>QPainter</code> object should be able to render HiDPI graphics.
== Qt Quick Controls 1 ==
If the QML contains Qt Quick Controls 1, all text components will be blur and small in HiDPI display. This is likely a Qt bug.
To solve this, we suggest you to migrate to Qt Quick Controls 2.

Revision as of 19:14, 8 September 2019

Introduction

HiDPI devices are very common today. Users need to scale up UI to make them looks like normal size. Common scale factors are: 1.25, 1.5, 1.75, 2, 3. This means UI dimensions are not integers anymore. Qt provides classes and functions that accept and return qreal instead of int. They usually end with F.

  • QRect --> QRectF
  • QPoint --> QPointF
  • QWidget::devicePixelRatio() --> QWidget::devicePixelRatioF()

KDE and Qt applications may render blur icons and graphics. This guide shows how to make everything sharp and clear in HiDPI devices. Both Qt 5 Widgets and Qt 5 Quick applications are supported.

Migrate to Qt 5 and KF5

Qt 4 doesn't support HiDPI rendering. Please migrate your application to Qt 5 and KF5.

Texts

You don't need to do anything special. Text rendering should support HiDPI out of box.

Icons

In your application's main function, add the following lines at the very beginning:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
    ...
}

Then all icons in your application should look sharp.

QPixmap

Change all QPixmap from

pixmap = QPixmap( width, height );

to

pixmap = QPixmap( width * dpr, height * dpr );
pixmap.setDevicePixelRatio(dpr);

So where is the dpr variable from? You can get it from any QWidget objects with function devicePixelRatioF(). F means the function return a float number (qreal). If you are not in a QWidget class context, you can get the value via:

const qreal dpr = qApp->devicePixelRatio();

And don't forget to change width and height from int to qreal.

QPainter

QPainter has various drawing functions. You need to change parameters of those functions from integer types:

  • QRect
  • QPolygon
  • QPoint
  • int

to floating types:

  • QRectF
  • QPolygonF
  • QPointF
  • qreal

For example, you need to change this code:

QPainter p;
p->drawText(0, 0, 12, 50, Qt::AlignLeft | Qt::AlignTop, text);

to:

QPainter p;
p->drawText(QRectF(0, 0, 12, 50), Qt::AlignLeft | Qt::AlignTop, text);

After all these changes, your QPainter object should be able to render HiDPI graphics.

Qt Quick Controls 1

If the QML contains Qt Quick Controls 1, all text components will be blur and small in HiDPI display. This is likely a Qt bug.

To solve this, we suggest you to migrate to Qt Quick Controls 2.