Solved shrinking large image into smaller QLabel
-
Hi all -
I've been asked to put the company logo into the main window of my app. The logo (a banner really) is considerably larger than the default size of the QLabel. I want it to expand proportionately if/as the user grows the window. Changing the size of the QLabel doesn't preserve the size when I add it to a horizontal layout (the label reverts to the image size). How do I go about handling this?
Thanks...
-
Hi
I assume
is not good enough as you want it to keep the aspect ratio ? -
Here's the top of my widget in Designer before I attempt a layout:
Admittedly not great, but tolerable.
Here's what happens when I try to join the logo, the spacer and the title horizontally:
-
@mzimmers
From my past experience, it is possible to do it with scaled content and spacers and size policies, but it never worked quite like I wanted it to, so I usually ended up subclassing the QLabel and drawing the banner by hand.it's like 4 lines of code and you do not need to rely on autogenerated code 🤷♂️
-
@J-Hilk I'm more than happy to take a different approach. But, what is the purpose of subclassing QLabel?
-
@mzimmers so that you can override the paintEvent and use the provided QPainter to paint your image (scaled) onto the Label 😉
-
@J-Hilk OK, I don't have all the details figured out, but I think I get the general sense:
- load the banner into a QImage
- use QPainter::drawImage to display the image
- use the overridden paintEvent to invoke the QPainter
- rely on the settings on the QLabel for resizing
Is that about it?
-
in essence yes, but you can only draw on the widget, if the QPainter(this) is created from the paintEvent or from functions that are called from within the paintEvent. You can't really do it outside of it ;)
-
@J-Hilk so:
- subclass QLabel
- override paintEvent
- create a QImage and QPainter within the paintEvent
- programmatically apply the subclassed label to my main widget
- manage sizing through the size policies
Better?
And...I'm going to accomplish this in 4 lines of code?
Thanks...
-
@mzimmers said in shrinking large image into smaller QLabel:
Better?
And...I'm going to accomplish this in 4 lines of code?
Thanks...jup for example:
#ifndef MYLABEL_H #define MYLABEL_H #include <QLabel> #include <QPainter> class MyLabel : public QLabel { Q_OBJECT public: explicit MyLabel(QWidget *parent = nullptr) : QLabel(parent) { } signals: public slots: protected: void paintEvent(QPaintEvent *event) override { Q_UNUSED(event) QPainter p(this); p.drawPixmap(rect(),pixmap()->scaled(size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); } }; #endif // MYLABEL_H
-
Nice. So, I create a QPixmap, apply my image to it and use that as the second argument to drawPixmap?
BTW: I don't see an overload to drawPixmap that 1) takes a rect as the first argument, and 2) takes 4 arguments. What am I missing?
Thanks...
-
Hi,
No, you just load MyLabel like you would with a normal QLabel using setPixmap. Nothing more to do.
In this case, drawPixamp only uses two arguments, all the rest are used by the
scaled
call. -
@SGaist ah, I didn't read the call to drawPixmap carefully enough; thanks.
Here's what I thought I should do:
void LogoLabel::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter p(this); const QString filename(":/CYBERDATA_IP_ENDPOINT_CO.png"); m_pixmap.load(filename); p.drawPixmap(rect(), pixmap()->scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); }
Do I also need a setPixmap call from the main widget?
EDIT:
Oh, I think I see now:
void LogoLabel::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter p(this); const QString filename(":/CYBERDATA_IP_ENDPOINT_CO.png"); bool rc; rc = m_pixmap.load(filename); if (rc) { setPixmap(m_pixmap); p.drawPixmap(rect(), pixmap()->scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } }
How does this look?
BTW: It seems like this routine gets called every time I add something to the QTableView in the main widget; is this to be expected, or have I done something unfortunate in my code?
Thanks...
-
You are over-engineering things here. Just use the code provided by @J-Hilk as is.
In your application:
logoLabel = new LogoLabel; logoLabel->setPixmap(QPixmap(":/CYBERDATA_IP_ENDPOINT_CO.png"));
And you are good to go.
Paint events might get called for various reasons. Adding stuff to your table might trigger some resizing or appearing of the scrollbars etc.
-
@SGaist OK, I could do it the say you and J-Hilk suggested.
In Designer, I'm experiencing some weird behavior when I try to add it to a horizontal layout. Basically it disappears. When I select everything I want to add to the layout, it looks like this:
Then when I press the layout button, it looks like this:
Is there something about using QLabels in layouts that I don't know?EDIT: it appears (and I admit I'm not at all sure) that it's not enough to specify a size, and fixed sizePolicy. To get this to display properly (though with no scaling), I had to set both the minimumSize and the maximumSize to the desired size.
This just underscores how much better I need to understand the whole Qt sizePolicy stuff. Can anyone recommend a good page that explains this?
Thanks...
-
@mzimmers said in shrinking large image into smaller QLabel:
Is there something about using QLabels in layouts that I don't know?
EDIT: it appears (and I admit I'm not at all sure) that it's not enough to specify a size, and fixed sizePolicy. To get this to display properly (though with no scaling), I had to set both the minimumSize and the maximumSize to the desired size.that behavior may also depend on the other sizepoliciey and min/max sizes of the other widgets in the layout. No easy way to say, what's going on 🤷♂️
This just underscores how much better I need to understand the whole Qt sizePolicy stuff. Can anyone recommend a good page that explains this?
Sorry I can't, it's something I always struggle with myself 🙈
-
Just realized I hadn't marked this as solved. Thanks to all who helped.
A footnote: I didn't mention anywhere above that when I created the QLabel in Designer, I had to promote it to my LogoLabel...took me a few minutes to figure this out when migrating this to a new project...