Qt: изменение размера метки QL, содержащей QPixmap, сохраняя при этом ее соотношение сторон
Я использую QLabel для отображения содержимого большего, динамически изменяющегося QPixmap для пользователя. Было бы неплохо сделать эту метку меньше/больше в зависимости от доступного пространства. Размер экрана не всегда так велик, как QPixmap.
как я могу изменить QSizePolicy и sizeHint() из QLabel для изменения размера QPixmap при сохранении соотношения сторон исходного QPixmap?
Я не могу изменить sizeHint() из QLabel, установка minimumSize() до нуля не помогает. Установка hasScaledContents() на QLabel позволяет расти, но нарушает соотношение сторон thingy...
подкласс QLabel действительно помог, но это решение добавляет слишком много кода для простой проблемы...
любые умные подсказки, как это сделать без подклассы?
4 ответов:
чтобы изменить размер метки, Вы можете выбрать соответствующую политику размера для метки, такую как расширение или минимальное расширение.
вы можете масштабировать растровое изображение, сохраняя его соотношение сторон при каждом изменении:
QPixmap p; // load pixmap // get label dimensions int w = label->width(); int h = label->height(); // set a scaled pixmap to a w x h 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_Haspectratiopixmaplabel.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)
Я просто использовать
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); } }отлично работает для меня до сих пор. Добро пожаловать.
я попытался с помощью phyatt это
AspectRatioPixmapLabelкласс, но испытал несколько проблем:
- иногда мое приложение вводило бесконечный цикл событий изменения размера. Я проследил это до звонка
QLabel::setPixmap(...)внутри метода resizeEvent, потому чтоQLabelна самом деле называетupdateGeometryвнутриsetPixmap, что может вызвать события изменения размера...heightForWidthказалось, игнорируется содержащим виджет (aQScrollAreaв моем случае), пока я не начал, устанавливая размер на этикетке, явный вызовpolicy.setHeightForWidth(true)- я хочу, чтобы метка никогда не росла больше, чем исходный размер пиксельного изображения
- о
minimumSizeHint()делает некоторую магию для меток, содержащих текст, но всегда сбрасывает политику размера по умолчанию, поэтому мне пришлось перезаписать еечто сказал, Вот мое решение. Я обнаружил, что могу просто использовать
setScaledContents(true)и пустьQLabelмаркер изменения размера. Конечно, это зависит от содержащего виджета / макета почитания элемент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_Haspectratiopixmaplabel.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(); } }
Comments