Cannot draw rect on QPixmap with QPainter - c++

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!

Related

QPainter composition mode example does not work as expected

I'm stuck with the difference from the book example and my version of it.
Qt version 5.12.0
As it's shown in the example:
As I see from my output:
First, destination and source In/Atop modes have not the same pictures. And, another noticed thing is, that we can see the rectangle as an additional layer between two.
Code to create the label:
QLabel* lblCreate(const QPainter::CompositionMode& mode){
QLabel* lbl = new QLabel;
lbl->setFixedSize(100, 100);
QRect rect(lbl->contentsRect());
QPainter painter;
// create first image
QImage sourceImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
painter.begin(&sourceImage);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setBrush(QColor(0, 255, 0));
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
// draw triangle
painter.drawPolygon(QPolygon() << rect.bottomLeft()
<< QPoint(rect.center().x(), 0)
<< rect.bottomRight());
painter.end();
// create second image
QImage resultImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
painter.begin(&resultImage);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(QColor(0, 255, 0), 4));
painter.setBrush(QColor(255, 0, 0));
// draw circle
painter.drawEllipse(rect);
painter.setCompositionMode(mode);
painter.drawImage(rect, sourceImage);
painter.end();
lbl->setPixmap(QPixmap::fromImage(resultImage));
return lbl;}
How it creates in main.cpp:
innerLayout_2->addWidget(lblCreate(QPainter::CompositionMode_Source), 0, 0);
innerLayout_2->addWidget(new QLabel("<CENTER>Source</CENTER>"), 1, 0);
My own suspicion is it may be depend on QImage::Format_ARGB32_Premultiplied.
Or it's mine handmade bug.
Anyway, I would be grateful for any ideas.
Thnx in advance!
The composition mode works on transparent backgrounds, in your case it is not, so you must set it before painting, for this you could use the fill() method:
QImage sourceImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
sourceImage.fill(Qt::transparent);
QImage resultImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
resultImage.fill(Qt::transparent);

Qt - QPainter not painting QPixmap w/ Aspect Ratio

I am painting in a custom widget to match the "Google-Styled" cards. I have most of the dimensions and font correct however upon painting an image it is always stretched. Here is a reference image and the relevant code. I would like to keep the image at it's default aspect ratio.
Image:
QRect topPortion = QRect(QPoint(0, 0), QSize(width(), (height()/4)*3));
QPainterPath backgroundPath;
backgroundPath.addRect(topPortion);
QPainterPath bottom = getCornerPath().subtracted(backgroundPath);
QRect bottomRect = QRegion(rect()).subtracted(QRegion(topPortion)).boundingRect();
painter.fillPath(getCornerPath(), m_bColor);
painter.fillPath(bottom, m_fColor);
painter.drawPixmap(topPortion, m_image.scaled(topPortion.size(), Qt::KeepAspectRatio, Qt::FastTransformation));//Issue
painter.setPen(QPen(QColor(50, 50, 50)));
painter.setFont(titleFont);
painter.drawText(QPointF(12, topPortion.height()+((bottomRect.height()-fontHeight)/2)+QFontMetrics(titleFont).ascent()), "Add Record");
painter.setFont(subtitleText);
painter.drawText(QPointF(12, topPortion.height()+((bottomRect.height()-fontHeight)/2)+fontHeight), "Add Record");
You're scaling your image with m_image.scaled function, however passing also to painter.drawPixmap function, the topPortion variable, and according to docs:
The pixmap is scaled to fit the rectangle, if both the pixmap and
rectangle size disagree.
So my solution is:
//Your's calculation area
QRect topPortion = QRect(QPoint(0, 0), QSize(width(), (height() / 4) * 3));
QPixmap pixmap = QPixmap(1024, 768); //Random image
pixmap.fill(Qt::red); //Random color
//Scaled size that will be used to set draw aera to QPainter, with aspect ratio preserved
QSize size = pixmap.size().scaled(topPortion.size(), Qt::KeepAspectRatio);
//Draw the pixmap inside the scaled area, with aspect ratio preserved
painter.drawPixmap(topPortion.x(), topPortion.y(), size.width(), size.height(), pixmap);

QT - pixmap artefacts on drag

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)

QT5: Drawing rect on top of another rect using drawPixMap()

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.

Qt- Change opacity of QPixmap

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