Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: INZER от Март 11, 2015, 12:37



Название: Масштабирование QGraphicsItem'ов
Отправлено: INZER от Март 11, 2015, 12:37
Есть вью с переопределнным событием вращения колесика мыши
Код:
void MapGraphicView::wheelEvent(QWheelEvent *event)
{
     if (event->delta() > 0)
        scale (1.1,1.1);
     else
        scale (1/1.1,1/1.1);
    event->accept();
}

На сцену добавляются элементы (QGraphicsPixmapItem, QGraphicsEllipseItem и др.)

Вопросы:
1) Как сделать так, чтобы QGraphicsPixmapItem не изменял свой масштаб?
2) Какие методы необходимо использовать, чтобы при крупном масштабе, когда появляются полосы прокрутки, прокручивать сцену, используя например перемещение мыши при зажатой левой кнопке



Название: Re: Масштабирование
Отправлено: INZER от Март 11, 2015, 14:28
Вопрос с отменой масштабирования для избранных итемов открыт, направьте в нужную сторону.


Немного модифицировал масштабирование (изображение центрируется в точке нахождения указателя мыши).
Добавил прокрутку, при нажатии кнопки мыши.
Вдруг кому пригодится код ниже.

Код:
#include <QGraphicsView>

class MapGraphicView: public QGraphicsView
{
    Q_OBJECT
public:
    MapGraphicView(QWidget * pWgt = 0);
    MapGraphicView(QGraphicsScene * pScene, QWidget * pWgt = 0);
protected:
    QPointF center;                                 // The center of visible area
    QPointF fixedPoint;                             // Fixation point (for scrolling)
    void setCenter (const QPointF& centerPoint);
    QPointF getCenter ();
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void wheelEvent(QWheelEvent *event);
    virtual void resizeEvent (QResizeEvent *event);
};

MapGraphicView::MapGraphicView(QWidget * pWgt):
    QGraphicsView (pWgt)
{
    fixedPoint = QPoint ();
}


MapGraphicView::MapGraphicView(QGraphicsScene * pScene, QWidget * pWgt):
    QGraphicsView (pScene, pWgt)
{
    fixedPoint = QPoint ();
}

void MapGraphicView::setCenter(const QPointF &centerPoint)
{
    QRectF visibleArea = mapToScene(rect()).boundingRect();        
    QRectF sceneBounds = sceneRect();                              
    double boundX = visibleArea.width()/2.0;
    double boundY = visibleArea.height()/2.0;
    double boundWidth = sceneBounds.width() - visibleArea.width();
    double boundHeight = sceneBounds.height() - visibleArea.height();
    QRectF bounds (boundX, boundY, boundWidth, boundHeight);
    center = centerPoint;

    if (!bounds.contains(centerPoint))
    {
        if (visibleArea.contains(sceneBounds))
        {
            center = sceneBounds.center();
        }
        else
        {
            if (centerPoint.x() > bounds.x() + bounds.width())
                center.setX(bounds.x() + bounds.width());
            else if (center.x() < bounds.x())
                center.setX(bounds.x());

            if (centerPoint.y() > bounds.y() + bounds.height())
                center.setY(bounds.y() + bounds.height());
            else if (centerPoint.y() < bounds.y())
                center.setY(bounds.y());
        }
        centerOn(center);
    }
}

QPointF MapGraphicView::getCenter()
{
    return center;
}

void MapGraphicView::mousePressEvent(QMouseEvent *event)
{
    fixedPoint = event->pos();
}

void MapGraphicView::mouseReleaseEvent(QMouseEvent *event)
{
    fixedPoint = QPoint ();
}

void MapGraphicView::mouseMoveEvent(QMouseEvent *event)
{
    if (!fixedPoint.isNull())
    {
        QPointF offset = mapToScene(fixedPoint.toPoint()) - mapToScene(event->pos());
        fixedPoint = event->pos();
        setCenter(getCenter() + offset);
    }
}

void MapGraphicView::wheelEvent(QWheelEvent *event)
{
    QPointF pointBeforeScale (mapToScene(event->pos()));
    QPointF visibleCenter = getCenter();
    double scaleFactor = 1.2;
    if (event->delta() > 0)
        scale(scaleFactor, scaleFactor);
    else
        scale(1.0/scaleFactor, 1.0/scaleFactor);
    QPointF pointAfterScale(mapToScene(event->pos()));
    QPointF offset = pointBeforeScale - pointAfterScale;
    QPointF newCenter = visibleCenter+offset;
    setCenter(newCenter);
    event->accept();
}

void MapGraphicView::resizeEvent(QResizeEvent *event)
{
    QRectF visibleArea = mapToScene(rect()).boundingRect();
    setCenter(visibleArea.center());
    QGraphicsView::resizeEvent(event);
}




Название: Re: Масштабирование
Отправлено: Igors от Март 11, 2015, 14:39
Никогда не пользовался QGraphicsScene (может там уже это давно решено), но рисовать приходилось немало, поэтому присоединяюсь к вопросу: а как быть с "немасштабируемыми" айтемами, такие найдутся (стрелочки координатных осей, надписи и.т.п.)?


Название: Re: Масштабирование QGraphicsItem'ов
Отправлено: GreatSnake от Март 11, 2015, 15:05
Код
C++ (Qt)
QGraphicsItem::setFrag( QGraphicsItem::ItemIgnoresTransformations );


Название: Re: Масштабирование QGraphicsItem'ов
Отправлено: Igors от Март 11, 2015, 15:21
Код
C++ (Qt)
QGraphicsItem::setFrag( QGraphicsItem::ItemIgnoresTransformations );
Вот он, идеальный ответ! (выжимка из букваря :)) Однако
Цитировать
The item ignores inherited transformations (i.e., its position is still anchored to its parent, but the parent or view rotation, zoom or shear transformations are ignored). This flag is useful for keeping text label items horizontal and unscaled, so they will still be readable if the view is transformed. When set, the item's view geometry and scene geometry will be maintained separately. You must call deviceTransform() to map coordinates and detect collisions in the view. By default, this flag is disabled. This flag was introduced in Qt 4.3.
А как же с вращением? Напр стрелочки (аттач) поворачиваться должны


Название: Re: Масштабирование QGraphicsItem'ов
Отправлено: INZER от Март 11, 2015, 15:27
Да, итем остается неизменным при масштабировании, однако, при изменении масштаба, он меняет свое положение относительно других итемов.
Видимо, нужно уменьшить/увеличить его координаты на величину скороллинга и, соответственно, сообщить ему, что координаты нужно пересчитать ...... буду курить тему дальше.
Спасибо за направление в нужную сторону!