如何修改我的Qt PaintEvent代码以相对于鼠标指针缩放显示的Pixmap



我有一个(到目前为止(相当简单的QWidget(大小约为300*300(,我正在使用它来显示一个大的QPixmap(例如5184*3456(。代码的关键部分如下所示:

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.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);

//QPointF whereScaled = m_where / (m_zoom * m_scale);
//qDebug() << "m_where:" << m_where.x() << m_where.y();
//qDebug() << whereScaled.x() << " " << whereScaled.y();
//painter.translate(-m_where);
painter.scale(m_zoom*m_scale, m_zoom*m_scale);
//painter.translate(m_where);
painter.drawPixmap(QPointF(0.0, 0.0), m_pixmap);
painter.setPen(QPen(QColor(255, 0, 0, alpha), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin));
painter.setBrush(Qt::NoBrush);
painter.drawRect(QRectF(0, 0, m_pixmap.width(), m_pixmap.height()).adjusted(-2, -2, 2, 2));
painter.end();
}
void DSSImageWidget::wheelEvent(QWheelEvent* e)
{
qreal degrees = -e->angleDelta().y() / 8.0;
//
// If zooming in and zoom factor is currently 1.0
// then remember mouse location
//
if ((degrees > 0) && (m_zoom == 1.0))
{
m_where = e->position();
}
qreal steps = degrees / 60.0;
qreal factor = m_zoom * std::pow(1.125, steps);

m_zoom = std::clamp(factor, 1.0, 5.0);
update();
Inherited::wheelEvent(e);
}

这缩放了窗口原点的像素图,这是一个很好的开始,但这不是我想要的。我想让它缩放像素图,这样鼠标指针下的图像部分就保持在原来的位置,并且图像围绕该点展开。

我已经用painter.translate((调用和我用来实际绘制像素图的位置播放了各种各样的曲调,但到目前为止,我失败了:(。

请一个知道这些东西是如何运作的人能让我摆脱痛苦,告诉我我是如何在这里实现目标的吗?

谢谢

经过相当长的代码处理,我终于解决了这个问题。考虑到它并不是那么简单,我在这里发布了代码的相关部分,希望它能帮助其他人。

来自标题:

typedef QWidget
Inherited;
private:
bool initialised;
qreal m_scale, m_zoom;
QPointF m_origin;
QPixmap & m_pixmap;
QPointF m_pointInPixmap;
inline bool mouseOverImage(QPointF loc)
{
qreal x = loc.x(), y = loc.y(), ox = m_origin.x(), oy = m_origin.y();
return (
(x >= ox) &&
(x <= ox + (m_pixmap.width() * m_scale)) &&
(y >= oy) &&
(y <= oy + (m_pixmap.height() * m_scale)));
};

源代码:

DSSImageWidget::DSSImageWidget(QPixmap& p, QWidget* parent)
: QWidget(parent),
initialised(false),
m_scale(1.0),
m_zoom(1.0),
m_origin(0.0, 0.0),
m_pixmap(p),
m_pointInPixmap((m_pixmap.width() / 2), (m_pixmap.height() / 2))
{
setAttribute(Qt::WA_MouseTracking);

setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
void DSSImageWidget::resizeEvent(QResizeEvent* e)
{
QSize sz = e->size();
qreal pixWidth = m_pixmap.width();
qreal pixHeight = m_pixmap.height();
qreal hScale = (qreal)sz.width() / pixWidth;
qreal vScale = (qreal)sz.height() / pixHeight;
m_scale = std::min(hScale, vScale);
qreal xoffset = 0.0, yoffset = 0.0;
if ((pixWidth * m_scale) < sz.width())
{
xoffset = (sz.width() - (pixWidth * m_scale)) / 2.0;
}
if ((pixHeight * m_scale) < sz.height())
{
yoffset = (sz.height() - (pixHeight * m_scale)) / 2.0;
}
m_origin = QPointF(xoffset, yoffset);
update();
Inherited::resizeEvent(e);
}
void DSSImageWidget::paintEvent(QPaintEvent* event)
{
QPainter painter;

qDebug() << "pointInPixmap: " << m_pointInPixmap.x() << m_pointInPixmap.y();
//
// Now calcualate the rectangle we're interested in
//
qreal width = m_pixmap.width();
qreal height = m_pixmap.height();
qreal x = m_pointInPixmap.x();
qreal y = m_pointInPixmap.y();
QRectF  sourceRect(
x - (x / m_zoom),
y - (y / m_zoom),
width / m_zoom,
height / m_zoom
);
qDebug() << "sourceRect: " << sourceRect.x() << sourceRect.y() << sourceRect.width() << sourceRect.height();
//
// Now calculate the rectangle that is the intersection of this rectangle and the pixmap's rectangle.
//
sourceRect &= m_pixmap.rect();
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);

painter.translate(m_origin);
painter.scale(m_zoom*m_scale, m_zoom*m_scale);
painter.translate(-m_origin);
//painter.drawPixmap(QPointF(0.0, 0.0), m_pixmap, sourceRect);
painter.drawPixmap(m_origin, m_pixmap, sourceRect);
painter.end();
}

#if QT_CONFIG(wheelevent)
void DSSImageWidget::wheelEvent(QWheelEvent* e)
{
qreal degrees = -e->angleDelta().y() / 8.0;
//
// If zooming in and zoom factor is currently 1.0
// then remember mouse location
//
if ((degrees > 0) && (m_zoom == 1.0))
{
QPointF mouseLocation = e->position();
if (mouseOverImage(mouseLocation))
{
m_pointInPixmap = QPointF((mouseLocation-m_origin) / m_scale);
}
else
{
m_pointInPixmap = QPointF((m_pixmap.width() / 2), (m_pixmap.height() / 2));
}
}
qreal steps = degrees / 60.0;
qreal factor = m_zoom * std::pow(1.125, steps);

m_zoom = std::clamp(factor, 1.0, 5.0);
if (degrees < 0 && m_zoom == 1.0)
{
m_pointInPixmap = QPointF((m_pixmap.width() / 2), (m_pixmap.height() / 2));
}
update();
Inherited::wheelEvent(e);
}
#endif

祝你一切顺利,大卫

最新更新