Qt:调整包含QPixmap的QLabel,同时保持宽高比
我使用QLabel向用户显示更大,dynamic更改的QPixmap的内容。 根据可用的空间,将这个标签变小/变大将会很好。 屏幕尺寸并不总是像QPixmap一样大。
如何修改QLabel的QSizePolicy
和sizeHint()
来调整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)
- 我希望标签永远不会增长超过原来的像素尺寸
-
QLabel
对minimumSizeHint()
的实现对包含文本的标签有一定的帮助,但总是将大小策略重置为默认值,所以我不得不覆盖它
这就是说,这是我的解决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); } }
迄今为止,对我来说是完美的。 别客气。