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(); }
-
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(); }