Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
QPainter: QImage vs QPixmap
Hi, I am making software that has a line plot. I have made the algorithms to make the plots, axis values, etc. by directly painting on
QWidget, but now, since the algorithms are all fully developed I want to move from drawing directly on
QWidgetto something more consistent such as
QImage. Since the painting is done using
QPainterI assume everything will work the same on
QImagebecause these both use the same paint engine as
QWidget. However, I am slightly confused regarding which
QImage. The Qt documentation is confusing, so I am trying to ask here if you have any knowledge about these topics then please share.
The Qt doc says:
drawPixmap()is faster on-screen while
drawImage()may be faster on a QPrinter or other devices.
but it also says:
To get the optimal rendering result using
QPainter, you should use the platform independent
QImageas paint device; i.e. using
QImagewill ensure that the result has an identical pixel representation on any platform.
This confuses me, the above two statements are for two different types: Devices and Platforms. So, a
QPixmapis better if I want to draw on a Device which is a screen because
drawPixmap()will only accepts a
QImageis better if I want to have support for different Platforms (such as Mac OS and Windows) but
drawImage()is inferior to
drawPixmap()when it comes to drawing on screen. If I want to have both, i.e. platform-independent fast on-screen drawing (which I am guessing is the most used/practical scenario), which one should I go with?
P.S. I have tried to search on Stack Exchange as well as here on the Qt forum, but usually the answers to the questions regarding which one to use, people just quote documentation from Qt docs. What I am looking for is a real answer that acts as a bridge between the above two statements from Qt Docs.
may be faster on a QPrinter or other devices.
"may" is very vague and usually means "I have not checked but it feels this way".
So I'd recommend going with QImage. If you notice any performance issues, then you can always use QPixmap and verify whether it really is faster or not.
my practical solution is that if I deal with an image that is supposed to be printed or saved, I store it in QImage and render on-screen using its method toPixmap().
If it is screen only I don't much care and stick to QPixmap.
Truth to tell though, I never came to any issues with using any so my main decision making between those two is how easily each of the types can be incorporated into the code (both types have somewhat different advantages when it comes to the methods they offer).
I never run into distortion or any other problems but then again, I develop for desktop only (on macOS and Windows mostly).
@artwaw Hi, thanks for the great answer. I am also developing only for desktop currently (both Mac OS and Windows), based on your answer I think I will stick with
QPixmapas 99% of the time I am just drawing on-screen and not printing or saving it. For the 1% of the time when I actually have to print or save it, I can use
toImage()to convert it into a
However, since you have experience in developing for desktop, I do have one more question for you: How do the different screen resolution affect the drawing operation? Suppose, I am writing software on a machine that has a 1080p monitor and so all my constant values, such as margins, etc., are based on the 1080p resolution. What happens when a user uses my software on a monitor with 4k resolution, will Qt know that the software was written on a 1080p monitor and now it is being displayed on a 4k monitor and so it will multiply all the constant values by 2 or do I have to take care of this internally while writing the software to check what kind of resolution it is being displayed on? I don't have a 4k resolution monitor so I cannot really check it myself.
@CJha It is complicated, as apart from the resolution desktops have ability to be scaled. In general, I use layouts combined with minimum size restrictions of each item that should require such constraint.
It all depends on the use cases you consider - for my working environment (I develop internal tools for my company) I know that I can expect no less than HD resolution, so all my UIs are scaled to look decent on HD.
If users find the UI too small they can resize the window accordingly - that's what layouts are for. It takes a bit of trial and error until you find the right combination of minimum sizes and other properties and how they combine with layouts to get what you need but it is worth it.
Good introduction to the subject is https://doc.qt.io/qt-5/highdpi.html - I don't know how advanced you are with UI design, so can't advise more on that. I hate tweaking UIs, so my approach is probably not the most efficient when it comes to the outcome but I happily trade off any small UI flaws for simplicity of the solution.
What also helped me a lot is reading the documentation about the layouts, with emphasis on scaling factors etc.
Also, should you develop for macOS and Windows, please make sure you thoroughly test UI on both as there are differences to the widget sizes and how layouts fit together. Small things but annoying sometimes.
@artwaw Thanks again! great reply! I understand resolution + desktop scaling can make it complex. I will read through the link you provided and try my best to get the scaling correct. I am very new to making UI in C++, I have made similar UI in Matlab so I do have some understanding and some algorithms for the UI (most of which are redundant since Qt manages those internally).
One last question: Do you think there are any disadvantages of drawing directly on a
QWidgetcompared to drawing on a
QPixmapand then displaying that
QWidget? I understand if I draw on
QPixmapthen it is easier to convert it into a
QImagefor printing/saving in an image format or to keep the
QPixmapobject in memory continuously, but apart from this, since both
QPixmapuses the same raster-based engine my understanding is it shouldn't make any difference at all.
Just let Qt do its work. If by drawing directly on QWidget you mean subclassing it and rewriting its Paint() method - don't do it unless you absolutely have to. Or, when you need to provide a delegate for a view.
So far I've not had the necessity to dive that deep.
And since you can display (and scale) images and videos using QLabel, push buttons can be readily supplied with an icon... I just had not need.
Then again, your needs might differ.