у меня есть QGraphicsView
и QGraphicsScene
, В зависимости от пользовательского ввода некоторые QGraphicsItem
может быть размещен на сцене. Этот предмет можно выбирать и перемещать.
Когда сцена больше, чем появляются полосы прокрутки вида (они устанавливаются так, чтобы показываться при необходимости).
Когда элемент перемещается пользователем к краю вида, ширина / высота сцены соответственно растягиваются — я делаю сцену больше.
Вопрос в том Как заставить полосы прокрутки прокручивать сцену, когда элемент находится около границы вида? Особенность я считаю распространенной в любом графическом редакторе. в MouseMoveEvent
Я делаю сцену больше, заставляю ползунки двигаться и соответственно обновляю видимый прямоугольник.
Это не работает, как задумано. Даже при том, что свитки приспосабливаются к новому размеру сцены, нет плавного движения в представлении. Есть ли лучший способ сделать это?
Некоторые объяснения:
itemUnderCursor = currently slected QGraphicsItem
qgv = QGraphicsView
Фрагмент кода:
// check if item is near the border
QPointF point = itemUnderCursor->mapToScene(itemUnderCursor->boundingRect().topLeft());
double delta = 0;
if(point.x() < visibleRect.left())
{
// prevent from drawing outside the scene
itemUnderCursor->setPos(visibleRect.left(), itemUnderCursor->scenePos().y());
if(event->scenePos().x() < oldMousePos.x()-3)
{
// stretch the scene
if(qgv->horizontalScrollBar()->value() <= 0)
setSceneRect(QRectF(QPointF(sceneRect().x() - 3, sceneRect().y()), sceneRect().bottomRight()));
/*
* disable signals from DrawingArea in order to avoid
* recursive calls of mouseMoveEvent then enabling them
* back to handle the rest of events
*/
this->blockSignals(true);
delta = point.x() - originalRect.left();
qgv->horizontalScrollBar()->setValue(hScrollOriginalValue + delta);
}
oldMousePos = event->scenePos();
this->blockSignals(false);
// update the visible rectangle
visibleRect = getVisibleRect(qgv);
}
if(point.x() + itemUnderCursor->boundingRect().width() > visibleRect.right())
{
// prevent from drawing outside the scene
itemUnderCursor->setPos(visibleRect.right() - itemUnderCursor->boundingRect().width(), itemUnderCursor->scenePos().y());
if(event->scenePos().x() > oldMousePos.x()+3)
{
// stretch the scene
if(qgv->horizontalScrollBar()->value() >= 0)
setSceneRect(QRectF(sceneRect().topLeft(), QPointF(sceneRect().bottomRight().x() + 3, sceneRect().bottomRight().y())));
/*
* disable signals from DrawingArea in order to avoid
* recursive calls of mouseMoveEvent then enabling them
* back to handle the rest of events
*/
delta = point.x() + itemUnderCursor->boundingRect().width() - originalRect.right();
this->blockSignals(true);
qgv->horizontalScrollBar()->setValue(hScrollOriginalValue + delta);
}
oldMousePos = event->scenePos();
this->blockSignals(false);
// update the visible rectangle
visibleRect = getVisibleRect(qgv);
}
Я делаю то же самое для верхней и нижней границы QGraphicsView
,
Похоже, что моя предыдущая попытка была ужасно сложной, хотя решение на самом деле очень простое.
Вместо предыдущего кода достаточно было написать:
qgv->ensureVisible(itemUnderCursor);
и убедитесь, что sceneRect()
не будет установлен с каким-либо значением, а оставлен для обработки самой сценой.
Это позволило сцене автоматически настроить свой размер в соответствии с элементами на ней и заставило полосы прокрутки следовать за движущимся элементом, когда он находится за пределами видимого прямоугольника. QGraphicsView
,
Других решений пока нет …