am I using drawPixmap() correctly?
Essentially my goal is to take an tileset image, and replace an individual tile with a custom tile image.
I'm able to get both images to load on the screen, but when I call drawPixmap(), then original image doesn't change at all.
Thanks in advance.
void replaceCustomTile(QPixmap custom, QPixmap target, int whichTile) {
QRect rect(0, 0 + (squareTileSize * whichTile), squareTileSize, squareTileSize);
QRect customRect = custom.rect();
QPainter painter(this);
painter.drawPixmap(rect, target, customRect);
painter.end();
}
EDIT:
This is how replaceCustomTile is called:
QPixmap terrainTiles(":/static/Terrain.png");
QPixmap customTile(":/static/Smiles.png");
replaceCustomTile(customTile, terrainTiles, 0);
To intialize QPainter by this it must be called from the widget paintEvent(QPaintEvent *) if you want to draw it on some widget. So, replaceCustomTile() should be called from the event handler in that case.
To draw some pixmap on top of another pixmap QPainter should be initialized by the target pixmap using QPainter::begin():
QPainter painter;
painter.begin(&target);
painter.drawPixmap(rect, custom);
painter.end();
The above code draws QPixmap custom into given QRect rect over QPixmap target. The target is modified.
Related
I have an issue with pixmaps created for drag events. For drag events of my derived QGraphicsRectItem I create a semi-transparent pixmap from that item.
In the debug build everything looks fine.
But in the release build the drag pixmap has some periodic and random artefacts
here is the code:
QPixmap MyGraphicsRectItem::toPixmap() const
{
QRect r = boundingRect().toRect();
QPixmap pixmap(r.width(), r.height());
QColor dragColor(color);
dragColor.setAlphaF(0.5);
QPainter painter;
painter.begin(&pixmap);
painter.fillRect(pixmap.rect(), dragColor);
painter.setPen(Qt::white);
QFont font("SegoeUI");
font.setBold(true);
painter.setFont(font);
painter.drawText(pixmap.rect(), QString(" ") + textItem->toPlainText());
if (pixItem != nullptr) {
painter.setOpacity(0.5);
painter.drawPixmap(pixItem->pos(), pixItem->pixmap());
}
painter.end();
return pixmap;
}
Could that be a kind of memory issue?
The QPixmap is initialized with uninitialized data. In Debug, this is often set to a fixed pattern, but in Release it is garbage.
You should fill the pixmap with transparent color before using it.
QPixmap::QPixmap(int width, int height)
Constructs a pixmap with the given width and height. If either width or height is zero, a null pixmap is constructed.
Warning: This will create a QPixmap with uninitialized data. Call fill() to fill the pixmap with an appropriate color before drawing onto it with QPainter.
(From Qt Docs)
I have a problem with drawing a rect on QPixmap, which I loaded from file. And I also want to use this pixmap as a icon in listView.
Code:
QPixmap pixmap(100, 100);//(temp);// = QPixmap(temp);
pixmap.load(temp);
QPainter* painter = new QPainter(&pixmap);
painter->setPen(QPen(Qt::blue, 4, Qt::SolidLine));
painter->drawRect(4, 4, 50, 50);
painter->end();
QIcon icon = QIcon();
icon.addPixmap(pixmap);
temp is a QString path to the file. It shows only a resized photo without rect. When I commented a line with load, then rect is shown with random background.
or maybe someone know how to do this with QIcon::paint function.
Thanks in advance!
How to change opacity of QPixmap?
I've set an image as background actually I want to change its opacity, Here is my code:
Call.h:
private:
QPixmap m_avatar;
Call.cpp:
void Call::resizeEvent(QResizeEvent *e)
{
QPalette pal = palette();
pal.setBrush(backgroundRole(), m_avatar.scaled(e->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
setPalette(pal);
}
I've changed resizeEvent function, but it doesn't change background's opacity.
void Call::resizeEvent(QResizeEvent *e)
{
QPixmap result_avatar(m_avatar.size());
result_avatar.fill(Qt::transparent);
QPainter painter;
painter.setOpacity(0.5);
painter.begin(&result_avatar);
painter.drawPixmap(0, 0, m_avatar);
painter.end();
QPalette pal = palette();
pal.setBrush(backgroundRole(), result_avatar.scaled(e->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
setPalette(pal);
}
Any suggestion?
You are not using local QPainter object. According to QWidget Events:
paintEvent() is called whenever the widget needs to be repainted.
Every widget displaying custom content must implement it. Painting
using a QPainter can only take place in a paintEvent() or a function
called by a paintEvent().
Here it works:
void Call::paintEvent(QPaintEvent *)
{
// create a new object scaled to widget size
QPixmap result_avatar = m_avatar.scaled(size());
QPainter painter(this);
painter.setOpacity(0.5);
// use scaled image or if needed not scaled m_avatar
painter.drawPixmap(0, 0, result_avatar);
}
Update for paiting on pixmap case
If it is needed only to paint with some opacity on a pixmap using QPainter, the opacity must be set only after QPainter activation by QPainter::begin(). So, after changing the order the pixmap result_avatar has two images (one resized with opacity 1 and original pixmap on top with opacity 0.5):
QPainter painter;
painter.begin(&result_avatar);
painter.setOpacity(0.5);
painter.drawPixmap(0, 0, m_avatar);
painter.end()
Rendering to bitmap, I have to create a QPainter. If I have to render multiple areas to multiple bitmaps, how do I reset the QPainter ?
QImage img1(scene1.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img1.fill(Qt::color0);
QPainter painter1(&img1);
painter1.setRenderHint(QPainter::Antialiasing);
scene1.render(&painter1);
painter1.end();
QImage img2(scene2.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img2.fill(Qt::color0);
QPainter painter2(&img2);
painter2.setRenderHint(QPainter::Antialiasing);
scene2.render(&painter2);
painter2.end();
How can I reuse the painter ? am I getting performance hits/higher memory usage by creating a new QPainter for each scene / image ?
Trying
QImage img(scene1.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::color0);
QPainter painter(&img);
painter.setRenderHint(QPainter::Antialiasing);
scene1.render(&painter);
painter.end();
img.save("img.png");
img = QImage(scene2.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::color0);
painter = QPainter(&img);
painter.setRenderHint(QPainter::Antialiasing);
scene2.render(&painter);
painter.end();
I get errors of the type
error: 'QPainter& QPainter::operator=(const QPainter&)' is private
You can reuse your QPainter with the following syntax:
QPainter painter;
painter.begin( &img1 );
...
painter.begin( &img2 );
...
But you can only use one QPainter for one QPaintDevice (in this case an image).
Read this.
It appears that QObject and Classes derived from it, as well as QPainter and maybe other classes, have private constructors (??? why)
So...
QImage img(scene1.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::color0);
QPainter* painter = new QPainter(&img);
painter->setRenderHint(QPainter::Antialiasing);
scene1.render(painter);
painter->end();
img.save("img.png");
img = QImage(scene2.sceneRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::color0);
painter = new QPainter(&img);
painter->setRenderHint(QPainter::Antialiasing);
scene2.render(painter);
painter->end();
delete painter;
I was writing this as vizhanyolajos was posting his answer, and I think I prefer that answer.
You do NOT need to write this:
QPainter* painter = new QPainter( &img );
you can write this instead:
QPainter painter( &img );
with this you don't have to think about the deleting of the obejct.
Yes, all the QObject derived classes have private copy constructors. You can read about the reasons here.
I think you do not need to worry about the reusing of the QImage. You can instantiate a new instance and use the being( ... ) function of the QPainter class.
How do you convert/paint a QGraphicsTextItem into a QPixmap?
You can add it to a QGraphicsScene (if it's not already inside one) and then render() the scene to a QPixmap using a QPainter
QPixmap pix(100, 100);
QPainter paint(&pix);
scene.render(&paint);
Or, you can save yourself the trouble and just use QPainter::drawText() after changing the current font of the painter. it should provide the same capabilities.
Maybe something like this-
QPixmap pix(100, 100);
QPainter paint(&pix);
paint.drawText(0, 0, "Hello World");
The QGraphicsTextItem::document() function is the back door you're looking for:
// pItem is a QGraphicsTextItem *
QPixmap srcPixmap(pItem->boundingRect().size().toSize());
QPainter tmpPainter(&srcPixmap);
pItem->document()->drawContents(&tmpPainter);
tmpPainter.end()