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

Recalcutating scale factor for viewing a Pixmap in a Widget



  • In a custom widget I calculate a scale factor to apply to the Pixmap when displaying it as follows (in showEvent())

                QSize sz = size();
                qreal hScale = (qreal)sz.width()/(m_pixmap.width() + 4);
                qreal vScale = (qreal)sz.height()/(m_pixmap.height() + 4);
                m_scale = m_default_scale = std::min(hScale, vScale);
    

    and then in paintEvent() I do:

        painter.begin(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
        QPointF center(m_pixmap.width() / qreal(2), m_pixmap.height() / qreal(2));
    
    
        //painter.translate(center);
        painter.scale(m_scale, m_scale);
        //painter.translate(-center);
    
        painter.drawPixmap(QPointF(0, 0), m_pixmap);
    
    

    and that works perfectly to scale the Pixmap (which is huge) to the window which is small.

    In my resizeEvent handler I have:

        QSize oldSize = e->oldSize();
        QSize newSize = e->size();
    
        qreal hScale = (qreal)(newSize.width()) / (qreal)(oldSize.width());
        qreal vScale = (qreal)(newSize.height()) / (qreal)(oldSize.height());
    
        qreal scale = std::max(hScale, vScale);
    
        m_scale *= scale;
        m_default_scale *= scale;
        update();
    
    

    Which just doesn't work as I expected when decreasing the window size - it seems to work ok when I increase the window size. I know I'm probably in line for a face-palm moment when you enlighten me!

    What have I got wrong here please?



  • I have a solution that works for the resizing. Thanks for pushing me in the right direction!!

    void DSSImageWidget::resizeEvent(QResizeEvent* e)
    {
        QSize sz = e->size();
        qreal hScale = (qreal)sz.width() / (m_pixmap.width() + 4);
        qreal vScale = (qreal)sz.height() / (m_pixmap.height() + 4);
        m_scale = std::min(hScale, vScale);
    
        update();
        Inherited::resizeEvent(e);
    }
    
    void DSSImageWidget::paintEvent(QPaintEvent* event)
    {
        QPainter painter;
        painter.begin(this);
    
        :
        painter.scale(m_factor*m_scale, m_factor*m_scale);
        :
    
        painter.end();
    }
    void DSSImageWidget::wheelEvent(QWheelEvent* e)
    {
        qreal degrees = -e->angleDelta().y() / 8.0;
        qreal steps = degrees / 60.0;
        qreal factor = m_factor * std::pow(1.125, steps);
            
        m_factor = std::clamp(factor, 1.0, 5.0)
        update();
    }
    


  • I don't even know why are you doing this in the resizeEvent...
    Just copy the code in your showEvent to your resizeEvent.
    And you don't need the showEvent, resizeEvent will also be called when first shown.



  • More explanation is in order. There's also code to zoom into the pixmap using keys/mousewheel which changes m_scale (but not m_default_scale). I would prefer to retain the zoom level (which is m_scale)when the window is resized, hence the attempt to scale the variables in resizeEvent().

    void DSSImageWidget::wheelEvent(QWheelEvent* e)
    {
        qreal degrees = -e->angleDelta().y() / 8.0;
        qreal steps = degrees / 60.0;
        qreal factor = std::pow(1.125, steps);
        m_scale *= factor;
        qreal maxscale = m_default_scale * 5.0;
        if (m_scale < m_default_scale) m_scale = m_default_scale;
        if (m_scale > maxscale) m_scale = maxscale;
        update();
    }
    

    Does that make more sense?



  • I have a solution that works for the resizing. Thanks for pushing me in the right direction!!

    void DSSImageWidget::resizeEvent(QResizeEvent* e)
    {
        QSize sz = e->size();
        qreal hScale = (qreal)sz.width() / (m_pixmap.width() + 4);
        qreal vScale = (qreal)sz.height() / (m_pixmap.height() + 4);
        m_scale = std::min(hScale, vScale);
    
        update();
        Inherited::resizeEvent(e);
    }
    
    void DSSImageWidget::paintEvent(QPaintEvent* event)
    {
        QPainter painter;
        painter.begin(this);
    
        :
        painter.scale(m_factor*m_scale, m_factor*m_scale);
        :
    
        painter.end();
    }
    void DSSImageWidget::wheelEvent(QWheelEvent* e)
    {
        qreal degrees = -e->angleDelta().y() / 8.0;
        qreal steps = degrees / 60.0;
        qreal factor = m_factor * std::pow(1.125, steps);
            
        m_factor = std::clamp(factor, 1.0, 5.0)
        update();
    }
    

Log in to reply