Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QGraphicsView doesn't respect heightForWidth() to maintain aspect ratio?



  • I created a small MVCE example to reproduce aspect ratio issue with an image on QGraphicsView.

    I realized the image scaling calculates the aspect ratio correctly but every time i resize QGraphicsView it ignores my heightForWidth() value (which actually returns the right height).

    ImageView.h

    #include <QGraphicsView>
    #include <QGraphicsScene>
    #include <QResizeEvent>
    #include <QWidget>
    #include <QImage>
    #include <QPixmap>
    
    class ImageView : public QGraphicsView
    {
        Q_OBJECT
    
    public:
        ImageView(QWidget* parent = nullptr);
    
        void setImage(const QImage& image);
    
        virtual int heightForWidth(int width) const override;
    
    protected:
    
        virtual void resizeEvent(QResizeEvent *event) override;
    
    private:
        QGraphicsScene* m_scene;
    
        QImage m_image;
        QPixmap m_pixImage;
    
        int m_rows;
        int m_cols;
    };
    

    ImageView.cpp

    #include "imageview.h"
    #include <QDebug>
    
    ImageView::ImageView(QWidget *parent) :
        QGraphicsView{parent},
        m_scene{new QGraphicsScene{this}},
        m_rows{0},
        m_cols{0}
    {
        setScene(m_scene);
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    
        QSizePolicy p(QSizePolicy::Minimum,QSizePolicy::Minimum);
        p.setHeightForWidth(true);
        setSizePolicy(p);
    
        setFrameStyle(0);
    
        setMouseTracking(true);
    }
    
    void ImageView::setImage(const QImage &image)
    {
        m_image = image;
    
        m_cols = image.width();
        m_rows = image.height();
    
        m_pixImage = QPixmap::fromImage(image);
    
        m_scene->addPixmap(m_pixImage);
        fitInView(m_scene->itemsBoundingRect(),Qt::KeepAspectRatio);
    }
    
    /* virtual */ int ImageView::heightForWidth(int width) const
    {
        int height = (m_cols != 0) ? width * m_rows / m_cols : width;
        qDebug() << "Height for width: " << height;
    
        return height;
    }
    
    void ImageView::resizeEvent(QResizeEvent *event)
    {
        m_scene->clear();
    
        qDebug() << "Graphics View: " << event->size();
        QPixmap pxImg = m_pixImage.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    
        if(!pxImg.isNull())
        {
          qDebug() << "Image: " << pxImg.size();
          qDebug() << "Graphics View: " << event->size();
          m_scene->addPixmap(pxImg);
        }
    
        fitInView(m_scene->itemsBoundingRect(),Qt::KeepAspectRatio);
        QGraphicsView::resizeEvent(event);
    }
    

    MainWindow.h

    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    };
    

    MainWindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        ui->graphicsView->setImage(QImage("656780.png"));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    Output:
    Height for width:  586 // ideal height for the width to maintain aspect ratio (width should be 781)
    Graphics View:  QSize(782, 544) // instead height is set to 544 (width should be 725)
    Image:  QSize(725, 544) // scaling the image to the resize event size with aspect ratio 
                            // turns out 725 is right for a width of 544
    Graphics View:  QSize(782, 544) // same here
    

    As a result of the output my image is never scaled to the exact size of the QGraphicsView on resizing.

    How do i solve this? Is my calculation wrong? Or am i missing something?


Log in to reply