How to use QPainter on QPixmap
Asked Answered
C

2

19

I'm a newbie to Qt/Embedded. I want to use QPainter to draw stuff on a QPixmap, which will be added to QGraphicsScene. Here is my code. But it does not show the drawings on the pixmap. It shows only the black pixmap.

int main(int argc, char **argv) {

  QApplication a(argc, argv);

  QMainWindow *win1 = new QMainWindow();
  win1->resize(500,500);
  win1->show();


  QGraphicsScene *scene = new QGraphicsScene(win1);
  QGraphicsView view(scene, win1);
  view.show();
  view.resize(500,500);

  QPixmap *pix = new QPixmap(500,500);
  scene->addPixmap(*pix);

  QPainter *paint = new QPainter(pix);
  paint->setPen(*(new QColor(255,34,255,255)));
  paint->drawRect(15,15,100,100);

  return a.exec();
}
Craven answered 26/7, 2013 at 18:47 Comment(2)
paint->setPen(*(new QColor(255,34,255,255))); what an horrible memory leak! Just do paint->setPen(QColor(255,34,255,255));Immethodical
QPainter leaks too, it also suppose to be used on stack.Olivier
P
24

You need to do the painting on the bitmap before you add it to the scene. When you add it to the scene, the scene will use it to construct a QGraphicsPixmapItem object, which is also returned by the addPixmap() function. If you want to update the pixmap after it has been added, you need to call the setPixmap() function of the returned QGraphicsPixmapItem object.

So either:

...
QPixmap *pix = new QPixmap(500,500);
QPainter *paint = new QPainter(pix);
paint->setPen(*(new QColor(255,34,255,255)));
paint->drawRect(15,15,100,100);
scene->addPixmap(*pix); // Moved this line
...

or:

...
QPixmap *pix = new QPixmap(500,500);
QGraphicsPixmapItem* item(scene->addPixmap(*pix)); // Save the returned item
QPainter *paint = new QPainter(pix);
paint->setPen(*(new QColor(255,34,255,255)));
paint->drawRect(15,15,100,100);
item->setPixmap(*pix); // Added this line
...
Promotive answered 26/7, 2013 at 19:24 Comment(0)
L
14

QPixmap should be created without new keyword. It's usually passed by value or reference, not by pointer. One of the reasons is that QPixmap is not capable of tracking its changes. When you add a pixmap to a scene using addPixmap, only the current pixmap is used. Further changes will not affect the scene. So you should call addPixmap after you make changes.

Also you need to destroy QPainter before you use the pixmap to ensure that all changes will be written to the pixmap and to avoid memory leak.

QPixmap pix(500,500);
QPainter *paint = new QPainter(&pix);
paint->setPen(QColor(255,34,255,255));
paint->drawRect(15,15,100,100);
delete paint;
scene->addPixmap(pix);
Latterll answered 26/7, 2013 at 19:24 Comment(3)
is it the same to encapsulate the QPainter calls between QPainter::begin and QPainter::end instead of destroy it?Clarita
begin is called automatically in the constructor. You can call end without deleting the object and call begin later to reuse the object. Of course, you must finally destroy it some time. But it's more convenient to create QPainter without new to make it deleted automatically. There is no point in preserving the same painter between two paint actions. Constructing painters is a cheap operation.Latterll
This answer was very helpful to me. I was accidentally calling QPainter::end() after updating a QPixmap value instance. This caused a segmentation fault that was difficult to fix. Yes, QPixmap is normally created with new keyword, but ctor QPainter(PaintDevice*) (or method begin(PaintDevice*)) requires a pointer. Be careful about using a pointer to a value instance of QPixmap!Gelding

© 2022 - 2024 — McMap. All rights reserved.