Как использовать QPainter на QPixmap

Я новичок в Qt/Embedded. Я хочу использовать QPainter для рисования элементов на QPixmap, которые будут добавлены к QGraphicsScene. Вот мой код. Но он не показывает рисунки на пиксельной карте. Он показывает только черное растровое изображение.

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();
}

person manmatha    schedule 26.07.2013    source источник
comment
paint->setPen(*(new QColor(255,34,255,255))); какая ужасная утечка памяти! Просто сделай paint->setPen(QColor(255,34,255,255));   -  person Jean-Michaël Celerier    schedule 22.05.2015
comment
QPainter тоже дает утечки, предполагается, что он будет использоваться в стеке.   -  person Marek R    schedule 22.05.2017


Ответы (2)


Вам нужно нарисовать растровое изображение прежде чем добавить его в сцену. Когда вы добавите его в сцену, сцена будет использовать его для создания объекта QGraphicsPixmapItem, который также возвращается функцией addPixmap(). Если вы хотите обновить растровое изображение после его добавления, вам нужно вызвать функцию setPixmap() возвращаемого объекта QGraphicsPixmapItem.

Так что либо:

...
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
...
person Daniel Hedberg    schedule 26.07.2013

QPixmap должен быть создан без ключевого слова new. Обычно он передается по значению или ссылке, а не по указателю. Одна из причин в том, что QPixmap не может отслеживать свои изменения. Когда вы добавляете растровое изображение в сцену с помощью addPixmap, используется только текущее растровое изображение. Дальнейшие изменения не повлияют на сцену. Поэтому вам следует вызвать addPixmap после внесения изменений.

Также вам необходимо уничтожить QPainter перед использованием растрового изображения, чтобы гарантировать, что все изменения будут записаны в растровое изображение и избежать утечки памяти.

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);
person Pavel Strakhov    schedule 26.07.2013
comment
это то же самое, что инкапсулировать вызовы QPainter между QPainter::begin и QPainter::end вместо их уничтожения? - person nkint; 27.07.2013
comment
begin вызывается автоматически в конструкторе. Вы можете вызвать end, не удаляя объект, и вызвать begin позже, чтобы повторно использовать объект. Конечно, вы должны окончательно уничтожить его когда-нибудь. Но удобнее создать QPainter без new, чтобы он удалялся автоматически. Нет смысла сохранять один и тот же рисовальщик между двумя действиями рисования. Конструирование маляров — дешевая операция. - person Pavel Strakhov; 27.07.2013
comment
Этот ответ был очень полезен для меня. Я случайно вызвал QPainter::end() после обновления экземпляра значения QPixmap. Это вызвало ошибку сегментации, которую было трудно исправить. Да, QPixmap обычно создается с ключевым словом new, но ctor QPainter(PaintDevice*) (или метод begin(PaintDevice*)) требует указателя. Будьте осторожны при использовании указателя на экземпляр значения QPixmap! - person kevinarpe; 28.06.2020