Как вернуть изображение в исходное центральное положение после увеличения, панорамирования и затем уменьшения масштаба?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Как вернуть изображение в исходное центральное положение после увеличения, панорамирования и затем уменьшения масштаба?

Сообщение Anonymous »

Я создаю виджет для просмотра изображений с возможностями увеличения и уменьшения масштаба, включая поддержку панорамирования (щелкните и перетащите, чтобы переместить изображение).
В настоящее время масштабирование выход сразу после увеличения масштаба работает как положено: изображение возвращается в исходное положение. Однако когда я увеличиваю масштаб, перемещаю изображение в другое положение, а затем уменьшаю его, изображение не возвращается в исходное центральное положение.
Демонстрационное видео:
https ://i.imgur.com/xgt9V2H.gif
Демонстрационный GIF:

Изображение

Черная область — это фон вида, она не должна быть видна.Мне нужна помощь с расчетами, необходимыми для правильного изменения положения изображения при уменьшении масштаба, особенно в этой части кода: if (коэффициент < 1,0) // Уменьшение масштаба { ... .
Минимальный воспроизводимый пример:
#include
#include
#include
#include

class ZoomGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
ZoomGraphicsView()
{
scene = new QGraphicsScene(this);
setScene(scene);

// Basic setup - explicitly disable scrollbars
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setRenderHint(QPainter::SmoothPixmapTransform);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
setFrameShape(QFrame::NoFrame);
setTransformationAnchor(QGraphicsView::NoAnchor);
setResizeAnchor(QGraphicsView::NoAnchor);
setBackgroundBrush(Qt::black);
setAlignment(Qt::AlignCenter);
setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);

// Initialize pixmap item
pixmapItem = new QGraphicsPixmapItem();
scene->addItem(pixmapItem);

// Initialize base scale
baseScale = 1.0;
currentScale = 1.0;
isZooming = false;

}

void setImage(const QImage& image)
{
QPixmap newPixmap = QPixmap::fromImage(image);
if (newPixmap.isNull())
return;

// Update pixmap
pixmapItem->setPixmap(newPixmap);

if (firstImage)
{
resetView();
firstImage = false;
}

// Update scene rect to match the viewport
scene->setSceneRect(viewport()->rect());
}

protected:
void wheelEvent(QWheelEvent* event) override
{
if (pixmapItem->pixmap().isNull())
return;

isZooming = true;

// Store cursor position relative to scene
QPointF mousePosScene = mapToScene(event->position().toPoint());
QPointF mousePosCurrent = event->position();

// Calculate zoom factor
double factor = pow(1.5, event->angleDelta().y() / 240.0);
double newScale = currentScale * factor;

// Handle zoom out specifically
if (factor < 1.0) // Zooming out
{
if (newScale < baseScale)
{
resetView();
isZooming = false;
event->accept();
return;
}

// 1. Get the current positions before any transformation
QRectF viewRect = viewport()->rect();
QPointF mousePos = event->position();
QPointF mousePosScene = mapToScene(mousePos.toPoint());

// 2. Calculate the view center and the distance from mouse to center
QPointF viewCenter = mapToScene(viewRect.center().x(), viewRect.center().y());
QPointF mouseOffset = mousePosScene - viewCenter;

// 3. Apply the new scale
QTransform newTransform;
newTransform.scale(newScale, newScale);
setTransform(newTransform);

// 4. Calculate how much the mouse point moved after scaling
QPointF newMousePosScene = mapToScene(mousePos.toPoint());
QPointF deltaPos = newMousePosScene - mousePosScene;

// 5. Adjust the view to maintain the mouse position
translate(deltaPos.x(), deltaPos.y());

// 6. Calculate the scaled image bounds
QRectF imageRect = pixmapItem->boundingRect();
QRectF scaledImageRect = QRectF(imageRect.topLeft() * newScale, imageRect.size() * newScale);

// 7. Ensure the view stays within bounds
QPointF currentCenter = mapToScene(viewRect.center().x(), viewRect.center().y());
QPointF newCenter = currentCenter;

// 8. Apply bounds to keep image filling the view
if (scaledImageRect.width() < viewRect.width())
newCenter.setX(scaledImageRect.center().x());
else
{
qreal minX = viewRect.width() / 2.0;
qreal maxX = scaledImageRect.width() - minX;
newCenter.setX(qBound(minX, currentCenter.x(), maxX));
}

if (scaledImageRect.height() < viewRect.height())
newCenter.setY(scaledImageRect.center().y());
else
{
qreal minY = viewRect.height() / 2.0;
qreal maxY = scaledImageRect.height() - minY;
newCenter.setY(qBound(minY, currentCenter.y(), maxY));
}

// 9. Update to the bounded position
centerOn(newCenter);
currentScale = newScale;

qDebug()

Подробнее здесь: https://stackoverflow.com/questions/791 ... er-zooming
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»