Ограничение предмета от перемещения на сцене QGraphicsView в соответствии с ограниченным прямоугольнымC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Ограничение предмета от перемещения на сцене QGraphicsView в соответствии с ограниченным прямоугольным

Сообщение Anonymous »

Я использую qgraphicsview , чтобы иметь возможность масштабировать/перемещаться по изображению, я работаю в этом коде, который основан на этом вопросе, он ограничивает изображение от перемещения за пределы границ .
С этим новым классом я стараюсь перемещать изображение в любом месте в виде просмотра, так как такая конкретная область (_pixmaprect) не выходит целый Out the Viewport Bounds. < /p>
в коде ниже, в зависимости от уровня масштаба, я не могу переместить изображение вокруг: < /p>
https : //i.imgur.com/z0lowpg.mp4
в масштабе 1,22
я могу перемещать ее только вокруг его начальной области, на больших масштабах im Способен переместить его повсюду, включая его полное перемещение за пределами границ просмотра, то, чего я хотел бы избежать. < /p>
Например, это нормально: < /p>

Это не так, изображение завершено снаружи :

< P> Я попытался создать очень минимальный пример, код не очень хорошо написан, но его понятно: < /p>
#include

class GraphicsView : public QGraphicsView
{
public:
QLabel* _posLabel = nullptr;
QGraphicsScene* _scene = nullptr;
QGraphicsPixmapItem* _pixmapItem = nullptr;
bool _isPanning = false;
qreal _currentScale = 1.0;
QPoint _lastMousePos;
QRect _pixmapRect;

GraphicsView(QWidget* parent, const QPixmap& pixmap) : QGraphicsView(parent)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setRenderHint(QPainter::SmoothPixmapTransform);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
setFrameShape(QFrame::NoFrame);
setTransformationAnchor(QGraphicsView::NoAnchor);
setResizeAnchor(QGraphicsView::NoAnchor);
setBackgroundBrush(Qt::NoBrush);
setAlignment(Qt::AlignCenter);
setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
setMouseTracking(true);
setFixedSize(parent->size());
setStyleSheet("*{ background-color: transparent; }");

_posLabel = new QLabel(this);
_posLabel->setFixedSize(300, 50);
_posLabel->setStyleSheet("QLabel { font-size: 18px; color : white; }");
_posLabel->move(0, 0);
_posLabel->setText("0,0 0x0\nscale: 0");

QList sbList{ new QSpinBox(this), new QSpinBox(this) };
for (int i = 0; i < 2; i++) // just to help debug
{
QSpinBox* sb = sbList;
sb->setRange(1, i ? height() : width());
sb->move( i ? 900 : 860, 0);
sb->setValue( i ? 50 : 50);
sb->setSingleStep(40);
sb->setFixedWidth(60);
connect(sb, &QSpinBox::valueChanged, [=](int value)
{
QPixmap pixmap2(pixmap.size());
pixmap2.fill(Qt::transparent);
QRect r(420, 250, sbList[0]->value(), sbList[1]->value());
QPainter painter(&pixmap2);
painter.drawPixmap(r.x(), r.y(), pixmap.copy(r));
_pixmapRect = r;
_pixmapItem->setPixmap(pixmap2);
});
}

QGraphicsPixmapItem* bgPixmapItem = new QGraphicsPixmapItem();
QPixmap bg(size());
bg.fill(QColor(0, 0, 0, 180));
bgPixmapItem->setPixmap(bg);

_pixmapItem = new QGraphicsPixmapItem();
_scene = new QGraphicsScene(this);
_scene->addItem(bgPixmapItem);
_scene->addItem(_pixmapItem);
setScene(_scene);
};

void centerScene()
{
// First check if the top left corner is in the middle of the view.
QPointF topLeft = mapFromScene(0, 0);
if (topLeft.x() > 0 || topLeft.y() > 0)
{
QTransform t;
t.translate(
topLeft.x() > 0 ? -topLeft.x() / _currentScale : 0,
topLeft.y() > 0 ? -topLeft.y() / _currentScale : 0
);
setTransform(t, true);
}
else
{
// If not, then check if perhaps the bottom right corner is.
QPointF bottomRight = mapFromScene(width(), height());
if (bottomRight.x() < width() || bottomRight.y() < height())
{
QTransform t;
t.translate(
bottomRight.x() < width() ? - (bottomRight.x() - width()) / _currentScale : 0,
bottomRight.y() < height() ? -(bottomRight.y() - height()) / _currentScale : 0
);
setTransform(t, true);
}
}

QRect pixmapRect = viewportTransform().mapRect(_pixmapRect);
_posLabel->setText(QString("%1,%2 %3x%4\nscale: %5")
.arg(pixmapRect.x()).arg(pixmapRect.y()).arg(pixmapRect.width()).arg(pixmapRect.height())
.arg(QString::number(_currentScale, 'f', 2)));
}

void mouseMoveEvent(QMouseEvent* event) override
{
if (!_isPanning)
return;
QPointF delta = mapToScene(event->pos()) - mapToScene(_lastMousePos);
QTransform t;
t.translate(delta.x(), delta.y());
setTransform(t, true);
centerScene();
_lastMousePos = event->pos();
event->accept();
}

void mousePressEvent(QMouseEvent* event) override
{
if (event->button() == Qt::LeftButton)
{
_isPanning = true;
_lastMousePos = event->pos();
setCursor(Qt::ClosedHandCursor);
event->accept();
}
}

void mouseReleaseEvent(QMouseEvent* event) override
{
if (event->button() == Qt::LeftButton)
{
_isPanning = false;
setCursor(Qt::ArrowCursor);
event->accept();
}
}

void wheelEvent(QWheelEvent* event) override
{
// Store cursor position relative to scene
QPointF mousePos = event->position(),
mousePosCurrent = mapToScene(mousePos.x(), mousePos.y());

// Calculate zoom factor
double factor = pow(1.5, event->angleDelta().y() / 240.0);
double newScale = _currentScale * factor;
if (newScale < 1.) { // Do not allow zooming out (in absolute)
factor /= newScale;
newScale = 1.;
}
else if (newScale > 50.) { // Do not allow zoom > 50x
factor = factor * 50. / newScale;
newScale = 50.;
}

// Zoom centered on the mouse cursor
QTransform t;
t.translate(mousePosCurrent.x(), mousePosCurrent.y());
t.scale(factor, factor);
t.translate(-mousePosCurrent.x(), -mousePosCurrent.y());
setTransform(t, true);

_currentScale = newScale;
centerScene();

event->accept();
}
};

class Widget : public QWidget
{
public:
QPixmap _pixmap;
Widget() : QWidget(nullptr)
{
QPixmap pixmap("image.png"); // image.png: Изображение
QSize size = pixmap.size();
setFixedSize(size);
QLabel* label = new QLabel(this);
label->setFixedSize(size);
label->setPixmap(pixmap);
GraphicsView* view = new GraphicsView(this, pixmap);
emit view->findChild()->valueChanged(0);
}
};

int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... strained-r
Ответить

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

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

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

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

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