Подтвердить что ты не робот

Как изменить размер изображения в Qt?

Я создал класс под названием ImageLabel, который расширяет QLabel. Я хочу, чтобы он сохранял соотношение размеров изображения, которое он отображает, независимо от того, насколько он растянут. Он отлично работает, когда вы увеличиваете окно. Проблема возникает, когда вы пытаетесь сделать окно меньше: оно не изменяет размер высоты, оно оставляет его растянутым. Как это исправить?


int ImageLabel::heightForWidth(int width) const {
    int height = (this->size.height()*width)/this->size.width();
    return height;
}

QSize ImageLabel::sizeHint() const {
    return this->size;
}

QSize ImageLabel::minimumSizeHint() const {
    return QSize(0, 0);
}

void ImageLabel::setSizePolicy(){
    QSizePolicy policy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    policy.setHeightForWidth(true);
    QLabel::setSizePolicy(policy);
    QLabel::setScaledContents(true);
}

void ImageLabel::setPixmap ( const QPixmap &pixmap ){
    this->size = pixmap.size();
    QLabel::setPixmap(pixmap);
}

int main(int argc, char *argv[]){
    QApplication a(argc, argv);

    QFrame *frame = new QFrame;
    QVBoxLayout *layout = new QVBoxLayout;
    frame->setLayout(layout);

    QPixmap map;
    map.load("test.png");
    ImageLabel *label = new ImageLabel;
    label->setSizePolicy();
    label->setPixmap(map);
    layout->addWidget(label);
    frame->show();

    return a.exec();
}

4b9b3361

Ответ 1

Есть несколько способов сделать это, но больше всего я бы рекомендовал, возможно, не бороться с макетной системой, пытаясь намекнуть на этот аспект. Как вы можете видеть, вам нужно попытаться реализовать ряд методов, пытаясь помочь макету.

Я могу предложить два примера. Ни один из них не использует макеты...

Первый использует дочерний элемент QLabel для отображения изображения и отключает фиксированный размер события изменения размера:

// imagelabel.h

class ImageLabel : public QWidget
{
    Q_OBJECT

public:
    explicit ImageLabel(QWidget *parent = 0);
    const QPixmap* pixmap() const;

public slots:
    void setPixmap(const QPixmap&);

protected:
    void resizeEvent(QResizeEvent *);

private slots:
    void resizeImage();

private:
    QLabel *label;
};

// imagelabel.cpp

ImageLabel::ImageLabel(QWidget *parent) :
    QWidget(parent)
{
    label = new QLabel(this);
    label->setScaledContents(true);
    label->setFixedSize(0,0);
}

void ImageLabel::resizeEvent(QResizeEvent *event) {
    QWidget::resizeEvent(event);
    resizeImage();
}

const QPixmap* ImageLabel::pixmap() const {
    return label->pixmap();
}

void ImageLabel::setPixmap (const QPixmap &pixmap){
    label->setPixmap(pixmap);
    resizeImage();
}

void ImageLabel::resizeImage() {
    QSize pixSize = label->pixmap()->size();
    pixSize.scale(size(), Qt::KeepAspectRatio);
    label->setFixedSize(pixSize);
}

Второй пример основан на ответе @Arnold_Spence. Он еще короче, поскольку он не использует дочерний QLabel. Он просто рисует pixmap в событии paint:

// imagelabel2.h

class ImageLabel2 : public QWidget
{
    Q_OBJECT

public:
    explicit ImageLabel2(QWidget *parent = 0);
    const QPixmap* pixmap() const;

public slots:
    void setPixmap(const QPixmap&);

protected:
    void paintEvent(QPaintEvent *);

private:
    QPixmap pix;
};

// imagelabel2.cpp

ImageLabel2::ImageLabel2(QWidget *parent) :
    QWidget(parent)
{
}

void ImageLabel2::paintEvent(QPaintEvent *event) {
    QWidget::paintEvent(event);

    if (pix.isNull())
        return;

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QSize pixSize = pix.size();
    pixSize.scale(event->rect().size(), Qt::KeepAspectRatio);

    QPixmap scaledPix = pix.scaled(pixSize,
                                   Qt::KeepAspectRatio,
                                   Qt::SmoothTransformation
                                   );

    painter.drawPixmap(QPoint(), scaledPix);

}

const QPixmap* ImageLabel2::pixmap() const {
    return &pix;
}

void ImageLabel2::setPixmap (const QPixmap &pixmap){
    pix = pixmap;
}

Ответ 2

В QLabel нет встроенного средства для сохранения пропорций изображения. Поскольку QLabel, вероятно, имеет функциональность, которая вам не нужна, вы должны подклассифицировать QWidget и переопределить paintEvent(), чтобы сделать изображение так, как вы хотите.