Search code examples
linuxqtqgraphicssceneqpainterhighdpi

How to disable Qt (5) high-dpi scaling temporarily?


I know that I can disable DPI scaling for the entire application by calling QApplication::setAttribute( Qt::AA_DisableHighDpiScaling ); before creating the QApplication instance. But, is it possible to set a QPainter/QGraphicsScene/QGraphicsView to ignore DPI?

I want all the widgets in my application to behave normally. I just want to draw a grid, in a view, without DPI scaling. That setting fixes the grid, but it prevents the widgets from scaling.

Note: I cannot easily just clobbering the scale of the graphical items, because I don't know the exact DPI. I haven't been able to find a value, anywhere, that explains exactly how QPainter draws. It seems to be quite magical. I also don't want to try to do that, because of the potential numeric instability of just tacking on additional factors. I'd like to remove a factor, temporarily...


Solution

  • Short answer is no; the high-dpi handling is all or nothing.

    For stuff you paint yourself with QPainter, there are a couple of effective workarounds. The first is to apply the inverse scaling. I wouldn't worry much about numeric instability here; in practice the QPainter ends up with a unity transform internally. So like this:

    QPainter p(myWidget);
    qreal inverseDPR = 1.0 / myWidget->devicePixelRatio();
    p.scale(inverseDPR, inverseDPR);
    

    The second way is to first render into a QImage, which by default has DPR==1. Then set the DPR of the image to the DPR of the widget before painting the image to the widget. That way, one avoids that the image gets scaled during painting. Like so:

    QImage img(...);
    // ... paint into image
    img.setDevicePixelRatio(myWidget->devicePixelRatio());
    QPainter p(myWidget);
    p.drawImage(... image ...);