Extend QPixmap on the right side without modify the content - c++

For a given QPixmap with 200x200 dimension, I want to extend it with 50px (transparent) on the right side, without scaling the existing content.
Is this possible on QPixmap or with any Qt helper class?

Just paint the original pixmap onto a new, extended one...
QPixmap original_pixmap = ...
QPixmap new_pixmap(original_pixmap.width() + 50, original_pixmap.height());
new_pixmap.fill(Qt::transparent);
QPainter painter(new_pixmap);
painter.drawPixmap(0, 0, original_pixmap);

Related

Why QWidget::Mask based on QPixmap works fine, but Bitmap doesn't

Target: make my widget rounded, using QWidget::setMask
At first, I want to make a mask using QRegion, but later I found that, make a rounded Rect based on region is a not simple way.
So I decided to use QBitmap.
QBitmap pixmap(size());//create image
QPainter pixmapPainter(&pixmap);
QPainterPath path;
path.addRoundedRect(0, 0, width(), height(), m_borderRadius, m_borderRadius);//fill rounded rect
pixmapPainter.fillPath(path, Qt::color1);
QWidget::setMask(pixmap.mask());
Result is:
But when I change my type to QPixmap and add the fill method
QBitmap pixmap(size());//
pixmap.fill(Qt::transparent);//
QPainter pixmapPainter(&pixmap);
pixmapPainter.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
path.addRoundedRect(0, 0, width(), height(), m_borderRadius, m_borderRadius);//
pixmapPainter.fillPath(path, Qt::white);
QWidget::setMask(pixmap.mask());
It shows me:
What's wrong with my first code?
As the comment by G.M. explains, the bitmap needs to be cleared first.
Also, a widget mask is not really the best choice here. A widget mask is intended for defining the areas where your widget will take mouse input. On most window systems, it will also cause transparency. But the edges will be aliased and not pretty. In order to make a non-rectangular widget with nice edges, one should use translucent widget background and anti-aliased painting - in addition to the widget mask for the mouse input.
This is shown and explained in Qt's shapedclock example.

How to save QPainter instance

I have a Qt application where I use QPainter to draw on a QPixmap which is then through QLabel displayed on the screen. Mainly it's drawing text and it's doing it several times every second.
I see it inefficient when the QPainter instance is constructing several times per second (including it's settings like font, pen etc.). So my question is, how can I save the instance of QPainter and reuse it later? I've tried this but it doesn't preserve the "settings" of the QPainter:
this->painter = new QPainter(&this->canvas); // this->cavas is a QPixmap
painter->setFont(this->font);
painter->setPen(this->font_color);
//...
painter->begin(&this->canvas);
painter->drawText(0, 0, 20, 20, "test");
painter->end();
Thanks

Qt C++ Can QGraphicsItem's paint() method access underlying pixels?

For visual markers in an imaging application on top of images I would like to enhance the contrast of said markers by using a fill color with high contrast to the local background (e.g. inverted). This requires for the object to read its background in a QGraphicsScene.
Is there an efficient (built-in) way of doing this or does it require something like rendering the scene without the marker, reading pixels in its position and then paint() the marker accordingly?
There is no straight way to get the rendered color of some point in QGraphicsScene. You should actually render the scene and see the color. One workaround is to render the scene to a QImage and pick the color from desired pixel:
QImage image=QImage(width,height,QImage::Format_RGB32);
QPainter painter( &image );
painter.setRenderHint(QPainter::Antialiasing);
myScene->render( &painter, image.rect(),QRectF(0,0,width,height), Qt::KeepAspectRatio );
painter.end();
QColor color = QColor(image.pixel(x,y));

Drawing a Tinted QPixmap using QPainter

I have a single-color transparent PNG loaded with a QPixmap, I want to draw this pixmap multiple times using different colors (e.g. once green, another yellow, etc). These QPixmaps are rendered through QPainter in the paintEvent function of a QWidget.
you can convert the pixmap into qimage and paint your own color .
1- Use QImage::fill(DesiredColor)
2- QPaintDevice supports QImage so use QPainter painter(&qImage); // 8 bit will not support in paint event .
then recreate QPixmap with image using QPixmap::fromImage(qImage);

Drawing a scalable QIcon using QPainter

I want to design a new QIcon and want it to look like a fixed text with a rounded rectangle around it
.-----.
| Phy |
`-----ยด
The icon is supposed to scale without the "pixel-blocks" effect when painting on a QPainter that eventually has a scale transformation applied (for example when I paint into a widget that is part of a QGraphicsView with a scale applied on its scene).
Therefor, I have difficulties knowing how I should paint my QIcon. If I do it in the following way, I will paint a QPixmap that always has a fixed amount of pixels, thus introducing the pixel-blocks effect inevitably when the scale is large enough
void MyWidget::drawIcon(QPainter *painter, QPoint pos) {
QPixmap pixmap = icon.pixmap(QSize(22, 22),
isEnabled() ? QIcon::Normal
: QIcon::Disabled,
isChecked() ? QIcon::On
: QIcon::Off);
painter->drawPixmap(pos, pixmap);
}
What I am looking for is a way similar to how QFont with drawText works. Regardless on how large my scale is, when I draw fonts it always looks sharp and I cannot detect individual pixels.
I imagine that I could tell QPainter to paint my icon into a given pixel rectangle, and QPainter transforms the rectangle itself before letting my QIconEngine::paint render the item into a possibly larger rectangle or pixmap. But I see no way how I could do something like this.
Am I just being stupid and not seeing the obvious solution?
I was indeed completely dump. I can just use QIcon::paint and pass it the rectangle. It will correctly delegate the request to the icon engine.
I do this by creating my icons/images as SVG files, and using QSvgRenderer to paint them onto a QPainter. The required classes are in the SVG module.