How to resize pixmap in Qt? - c++

I am trying to use a custom icon in a QtMessageBox, but can't resize the icon at all. The box shows up fine, but the icon is too large.
I've tried code from a similar question, but it didn't work.
QPixmap p(80,80);
p.scaled(80,80); //this doesn't seem to change anything
p.load("checkmark.png");
box->setIconPixmap(p);
How do I do this?

It is pointless to scale the pixmap before loading it, scale it afterwards.
QPixmap p("checkmark.png");
auto newPixmap = p.scaled(80, 80);
box->setIconPixmap(newPixmap);

Related

Best way for changeable Qt canvas

What is the most effective way of creating "canvas" with high change frequency in Qt?
Currently I have a main application window (QWidget) where I create a QPixmap and set it to a QLabel:
QPixmap *canvas = new QPixmap(500, 500);
QLabel *area = new QLabel(this);
area->setPixmap(canvas);
The problem is that I have to call area->setPixmap(canvas); after every change I make on the pixmap so that it can be displayed (I'm counting there will be normally several changes every second). Is this way ok? Or is there a better/faster/more efficient solution?
PeterT and Jeremy both have good solutions. Which one is best depends on your needs.
If you are moving items around and changing them, use a QGraphicsScene to store the data you want to display and readily manipulate it. Use a QGraphicsView to display the result.
If you are already doing the rendering elsewhere as a QPixmap and just want to draw the result, subclassing QWidget and drawing it in the paintEvent using QPainter may be simpler. Remember to call update(), though!

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.

How to resize QWidget in a layout while aligning it to the center and maintaining aspect ratio

Ok, so I'd like to display an image with qt where the image resizes with the browser and maintains the aspect ratio while also remaining centered in the window. I can get the resizing with aspect ratio to work correctly, but when I align it with Qt::AlignCenter, the qwidget no longer resizes (remains a fixed size). So basically, I can get either option to work but not together.
A good example of what I'm trying to do would be the imshow() function in matlab. This resizes the image while maintaining the aspect ratio and also centering the image in the window. The code I have is soemthing like this:
void roilayout::resizeEvent(QResizeEvent *event)
{
QSize p(roiview->refimage->size());
p.scale(roiview->view->size(), Qt::KeepAspectRatio);
roiview->view->resize(p);
}
and in the constructor:
roiview = new roiwindow;
roiview->view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
roiview->view->setCursor(Qt::CrossCursor);
roiview->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
roiview->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QHBoxLayout *layoutContainer = new QHBoxLayout;
layoutContainer->addWidget(roiview->view);
setLayout(layoutContainer);
I searched google and couldnt find anything. Also asked a similar question a little while back but from the answers it appears I didn't ask the question clearly enough. Thanks.
A couple of things: First it would be helpful to know what type of control "view" is.
Also, I don't think you should need to resize the child control "view" (whatever type it is) within the parent's resizeEvent() callback.
A better solution might be to set the sizeHint policy on the child widget to automatically expand.

Qt - QGraphicsView without ScrollBar

I am trying to show a picture in it's full view using QGraphicsScene. But when ever I put the QgraphicsScene inside the QGraphicsView, I am getting a scroll bar. I tried so many ways But all are went to veins. So can anybody tell me how to obtain the full view without the scrollbar.
You might be getting scrollbars because the scene is larger than the usable area within the graphics view. By default, a QGraphicsView comes with a 1-pixel margin. To fix this, you can try:
QRect rcontent = graphicsView.contentsRect();
graphicsView.setSceneRect(0, 0, rcontent.width(), rcontent.height());
I had been getting scrollbars because I was manually setting the scene rect to the size of the graphics item I was adding -- which was as large as the QGraphicsView widget. I wasn't taking into account the margin.
QGraphicsView v;
v.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
v.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
To adjust the scrolling programmatically once these have been hidden, use one of the overloads of v.ensureVisible().

How to set an initial size of a QScrollArea?

I know that this is a very specific C++ and Qt related question, but maybe someone can help me, anyway ...
See the code below: I want to display an image within a scroll area. The view port of the scroll area shall have a defined initial size. That means, if the image's size is bigger than the initial size of the view port, scroll bars will be visible, otherwise not.
// create label for displaying an image
QImage image( ":/test.png" );
QLabel *label = new QLabel( this );
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new QScrollArea( this );
area->setWidget( label );
// set the initial size of the view port
// NOTE: This is what I'd like to do, but this method does not exist :(
area->setViewPortSize( QSize( 300, 300 ) );
It shall be possible to resize the whole application so that the view port will get another size than the initial one.
Unfortunatelly I was not able to find out, how to set the size of the view port. Qt's layout mechanism seems to set a default size for the view port, but up to now I was not able to change it. Setting a new size with
area->setMinimumSize( QSize( 300, 300 ) );
will actually set the demanded size, but then the scroll area looses the ability to get resized to a size smaller than 300x300.
Any ideas?
I think that you are looking at the problem the wrong way. The QScrollArea is just a widget that you put in a frame or QMainWindow. The size of the widget is controlled by the layout of the widget that contains it.
Take a look at this example from Trolltech: Image Viewer Example
You can try:
class MyScrollArea : public QScrollArea
{
virtual QSize sizeHint() const { return QSize( 300, 300 ); }
};
// create label for displaying an image
QImage image( ":/test.png" );
Label *label = new QLabel;
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new MyScrollArea( this );
area->setWidget( label );
However layout and Qt is amazingly Voodoo. It is IMO its least functional part.
if that doesn't work, try calling QWidget::resize() on various widgets.
Is the scroll area the top level widget? If so, simply call
area->resize(300,300);
If it's inside a hierarchy you need to resize the toplevel appropriately (complex), or set the minimumSize of the area. You could also try to experiment with the LayoutPolicy - assuming the sizeHint is QSize(300,300) you can give it the appropriate size policy according to what's defined in https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
I don't think you can do exactly that very easily, which is (if I'm reading correctly), size the widget so that the internal area is 300x300. You might be able to fudge it, however, since a scroll area is a type of frame, which inherits from QWidget. This means you could just call area->resize( 300 + fudge, 300 + fudge ), where your fudge values account for the extra bit taken up by the frame's drawing.
I'm not sure this would work in a dynamically resizable dialog, however. I haven't ever done anything quite like this.
If you're trying to display an image inside a scroll area, your best bet isn't going with a label.
You should try using a QGraphicsView/QGraphicsScene/QGraphicPixmapItem (instead of the Scroll Area and label). The performance is far better when displaying images. The scroll area and label will re-draw the image very poorly as you move around using the scroll bars.
For example, you have a ".ui" file with a QGraphicsView on the gui called "qgvImageView" and a QImage called "image"...
QGraphicsScene *scene = new QGraphicsScene(qgvImageView);
QPixmap pixTmp(QPixmap::fromImage(image));
QGraphicsPixmapItem * ppixItem = scene->addPixmap( pixTmp );
ppixItem->setPos(0,0);
Check out the QT Documentation. BTW: This was introduced in Qt 4.2
I'm not sure if this will specifically fix the problem, but there is a chance that the QGraphicsView will react better to what you're trying to do.
How about using
area->setGeometry(int x, int y, int w, int h);