Qt:调整包含QPixmap的QLabel,同时保持宽高比

我使用QLabel向用户显示更大,dynamic更改的QPixmap的内容。 根据可用的空间,将这个标签变小/变大将会很好。 屏幕尺寸并不总是像QPixmap一样大。

如何修改QLabel的QSizePolicysizeHint()来调整QPixmap的大小,同时保持原始QPixmap的纵横比?

我无法修改QLabel的sizeHint() ,将minimumSize()设置为零不起作用。 在QLabel设置hasScaledContents()允许增长,但打破长宽比thingy …

子类化QLabel确实有帮助,但是这个解决scheme仅仅为一个简单的问题添加了太多的代码。

任何智能提示如何完成这个没有子类?

为了更改标签尺寸,您可以为标签select适当的尺寸策略,如展开或最小展开。

您可以通过每次更改时保持纵横比来缩放像素图:

 QPixmap p; // load pixmap // get label dimensions int w = label->width(); int h = label->height(); // set a scaled pixmap to awxh window keeping its aspect ratio label->setPixmap(p.scaled(w,h,Qt::KeepAspectRatio)); 

有两个地方你应该添加这个代码:

  • 当像素图更新时
  • 在包含标签的小部件的resizeEvent

我已经抛光了QLabel这个缺失的子类。 这是真棒,运作良好。

aspectratiopixmaplabel.h

 #ifndef ASPECTRATIOPIXMAPLABEL_H #define ASPECTRATIOPIXMAPLABEL_H #include <QLabel> #include <QPixmap> #include <QResizeEvent> class AspectRatioPixmapLabel : public QLabel { Q_OBJECT public: explicit AspectRatioPixmapLabel(QWidget *parent = 0); virtual int heightForWidth( int width ) const; virtual QSize sizeHint() const; QPixmap scaledPixmap() const; public slots: void setPixmap ( const QPixmap & ); void resizeEvent(QResizeEvent *); private: QPixmap pix; }; #endif // ASPECTRATIOPIXMAPLABEL_H 

aspectratiopixmaplabel.cpp

 #include "aspectratiopixmaplabel.h" //#include <QDebug> AspectRatioPixmapLabel::AspectRatioPixmapLabel(QWidget *parent) : QLabel(parent) { this->setMinimumSize(1,1); setScaledContents(false); } void AspectRatioPixmapLabel::setPixmap ( const QPixmap & p) { pix = p; QLabel::setPixmap(scaledPixmap()); } int AspectRatioPixmapLabel::heightForWidth( int width ) const { return pix.isNull() ? this->height() : ((qreal)pix.height()*width)/pix.width(); } QSize AspectRatioPixmapLabel::sizeHint() const { int w = this->width(); return QSize( w, heightForWidth(w) ); } QPixmap AspectRatioPixmapLabel::scaledPixmap() const { return pix.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); } void AspectRatioPixmapLabel::resizeEvent(QResizeEvent * e) { if(!pix.isNull()) QLabel::setPixmap(scaledPixmap()); } 

希望有所帮助! (更新resizeEvent ,每@ dmzl的答案)

我尝试使用phyatt的AspectRatioPixmapLabel类,但遇到了一些问题:

  • 有时候我的应用程序进入了一个无限循环的resize事件。 我追溯到QLabel::setPixmap(...)在resizeEvent方法的调用,因为QLabel实际上调用updateGeometry内的setPixmap ,这可能会触发resize事件…
  • 在我开始为标签设置尺寸策略之前, heightForWidth似乎被包含的小部件(一个QScrollArea在我的例子中)忽略,显式调用policy.setHeightForWidth(true)
  • 我希望标签永远不会增长超过原来的像素尺寸
  • QLabelminimumSizeHint()的实现对包含文本的标签有一定的帮助,但总是将大小策略重置为默认值,所以我不得不覆盖它

这就是说,这是我的解决scheme。 我发现我可以使用setScaledContents(true)并让QLabel处理resize。 当然,这取决于包含小部件/布局尊重heightForWidth

aspectratiopixmaplabel.h

 #ifndef ASPECTRATIOPIXMAPLABEL_H #define ASPECTRATIOPIXMAPLABEL_H #include <QLabel> #include <QPixmap> class AspectRatioPixmapLabel : public QLabel { Q_OBJECT public: explicit AspectRatioPixmapLabel(const QPixmap &pixmap, QWidget *parent = 0); virtual int heightForWidth(int width) const; virtual bool hasHeightForWidth() { return true; } virtual QSize sizeHint() const { return pixmap()->size(); } virtual QSize minimumSizeHint() const { return QSize(0, 0); } }; #endif // ASPECTRATIOPIXMAPLABEL_H 

aspectratiopixmaplabel.cpp

 #include "aspectratiopixmaplabel.h" AspectRatioPixmapLabel::AspectRatioPixmapLabel(const QPixmap &pixmap, QWidget *parent) : QLabel(parent) { QLabel::setPixmap(pixmap); setScaledContents(true); QSizePolicy policy(QSizePolicy::Maximum, QSizePolicy::Maximum); policy.setHeightForWidth(true); this->setSizePolicy(policy); } int AspectRatioPixmapLabel::heightForWidth(int width) const { if (width > pixmap()->width()) { return pixmap()->height(); } else { return ((qreal)pixmap()->height()*width)/pixmap()->width(); } } 

我只是使用contentsMargin来修复宽高比。

 #pragma once #include <QLabel> class AspectRatioLabel : public QLabel { public: explicit AspectRatioLabel(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); ~AspectRatioLabel(); public slots: void setPixmap(const QPixmap& pm); protected: void resizeEvent(QResizeEvent* event) override; private: void updateMargins(); int pixmapWidth = 0; int pixmapHeight = 0; }; 
 #include "AspectRatioLabel.h" AspectRatioLabel::AspectRatioLabel(QWidget* parent, Qt::WindowFlags f) : QLabel(parent, f) { } AspectRatioLabel::~AspectRatioLabel() { } void AspectRatioLabel::setPixmap(const QPixmap& pm) { pixmapWidth = pm.width(); pixmapHeight = pm.height(); updateMargins(); QLabel::setPixmap(pm); } void AspectRatioLabel::resizeEvent(QResizeEvent* event) { updateMargins(); QLabel::resizeEvent(event); } void AspectRatioLabel::updateMargins() { if (pixmapWidth <= 0 || pixmapHeight <= 0) return; int w = this->width(); int h = this->height(); if (w <= 0 || h <= 0) return; if (w * pixmapHeight > h * pixmapWidth) { int m = (w - (pixmapWidth * h / pixmapHeight)) / 2; setContentsMargins(m, 0, m, 0); } else { int m = (h - (pixmapHeight * w / pixmapWidth)) / 2; setContentsMargins(0, m, 0, m); } } 

迄今为止,对我来说是完美的。 别客气。