I have written application that draws two smiling faces:
First one is painted directly on QWidget:
void DirectFace::paintEvent(QPaintEvent *ev)
{
QPainter painter(this);
paintFace(painter);
}
Second one is painted on a QPixmap
, which in turn is blitted to widget:
void BufferedFace::paintEvent(QPaintEvent *ev)
{
QPixmap buffer(width(), height());
buffer.fill(Qt::transparent);
QPainter painter(&buffer);
paintFace(painter);
QPainter p(this);
p.drawPixmap(ev->rect(), buffer, ev->rect());
}
So far so good. I wanted to see how my app looks like on high resolution screen (I don't have one), so I set QT_SCALE_FACTOR=2
and run my app:
First face is sharp and crisp, whereas the seconf one is pixelated. That's because it is drawn to low resolution pixmap. So I have enlarged that QPixmap
and set correct devicePixelRatio
:
void BufferedFace::paintEvent(QPaintEvent *ev)
{
qreal pixelRatio = qApp->devicePixelRatio();
QPixmap buffer(width() * pixelRatio, height() * pixelRatio);
buffer.setDevicePixelRatio(pixelRatio);
buffer.fill(Qt::transparent);
QPainter painter(&buffer);
paintFace(painter);
QPainter p(this);
p.drawPixmap(ev->rect(), buffer, ev->rect());
}
Result:
Second face looks like it's drawn with correct resolution but then upscaled. Now I'm stuck. How to draw on QPixmap
and then draw that QPixmap
so it works correctly on Retina/HiDPI screens?
Whole application:
#include <QtWidgets>
class SmilingFace : public QWidget
{
public:
SmilingFace(QWidget *parent) : QWidget(parent) {};
void paintFace(QPainter &painter);
};
class DirectFace : public SmilingFace
{
public:
DirectFace(QWidget *parent) : SmilingFace(parent) {}
void paintEvent(QPaintEvent *ev) override;
};
class BufferedFace : public SmilingFace
{
public:
BufferedFace(QWidget *parent) : SmilingFace(parent) {}
void paintEvent(QPaintEvent *ev) override;
};
void SmilingFace::paintFace(QPainter &painter)
{
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(Qt::lightGray));
painter.drawEllipse(1, 1, width()-2, height()-2);
painter.setPen(Qt::white);
painter.setFont(QFont("", 32));
painter.drawText(rect(), Qt::AlignHCenter, ";)");
}
void DirectFace::paintEvent(QPaintEvent *ev)
{
QPainter painter(this);
paintFace(painter);
}
void BufferedFace::paintEvent(QPaintEvent *ev)
{
QPixmap buffer(width(), height());
buffer.fill(Qt::transparent);
QPainter painter(&buffer);
paintFace(painter);
QPainter p(this);
p.drawPixmap(ev->rect(), buffer, ev->rect());
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("HiDPI");
DirectFace d(&w);
d.resize(48, 48);
d.move(16, 16);
BufferedFace i(&w);
i.resize(48, 48);
i.move(16 + 48 + 16, 16);
w.show();
return a.exec();
}