如何在QGraphicsView中平移图像

Der*_*rek 21 c++ graphics qt qgraphicsview

我目前能够将我的图像加载到grahpics场景中,然后再加载到QGraphicsViewer中.

我可以通过检测QEvent :: Wheel然后调用graphicsViews的scale()函数来实现缩放功能.

但是,我似乎无法弄清楚如何使平移功能正常工作.我基本上想要检测鼠标何时单击图像,然后将图像与鼠标一起向左,向右,向上或向下移动.

截至目前,我基本上有一个MouseFilter类,它正在检测事件,并根据事件类型执行不同的操作.我将该监听器附加到QGraphicsView对象

neu*_*rte 44

如果有人想知道如何自己做,实际上很简单.这是我的应用程序中的代码:

class ImageView : public QGraphicsView
{
public:
    ImageView(QWidget *parent);
    ~ImageView();

private:
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);

    bool _pan;
    int _panStartX, _panStartY;
};
Run Code Online (Sandbox Code Playgroud)

您需要存储拖动的起始位置,例如像这样(我使用了右键):

void ImageView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton)
    {
        _pan = true;
        _panStartX = event->x();
        _panStartY = event->y();
        setCursor(Qt::ClosedHandCursor);
        event->accept();
        return;
    }
    event->ignore();
}
Run Code Online (Sandbox Code Playgroud)

此外,您需要清除标志并在释放按钮后恢复光标:

void ImageView::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton)
    {
        _pan = false;
        setCursor(Qt::ArrowCursor);
        event->accept();
        return;
    }
    event->ignore();
}
Run Code Online (Sandbox Code Playgroud)

要实际管理拖动,您需要覆盖鼠标移动事件.QGraphicsView继承了QAbstractScrollArea,并且可以轻松访问其滚动条.您还需要更新平移位置:

void ImageView::mouseMoveEvent(QMouseEvent *event)
{
    if (_pan)
    {
        horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - _panStartX));
        verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - _panStartY));
        _panStartX = event->x();
        _panStartY = event->y();
        event->accept();
        return;
    }
    event->ignore();

}
Run Code Online (Sandbox Code Playgroud)

  • **无视** - 不要使用 ::scrollContentsBy - 根据文档,您应该只使用滚动条。“调用此函数以编程方式滚动是一个错误,请改用滚动条(例如,通过直接调用 QScrollBar::setValue())。” (2认同)

Ste*_*Chu 15

QGraphicsView具有内置的鼠标平移支持.设置正确的DragMode,它将处理其余的.您需要启用滚动条才能工作.


小智 5

neuviemeporte解决方案要求将QGraphicsView子类化。

无需使用eventFilter子类化视图即可获得另一种有效的拖动实现。如果您不需要自定义QGraphicsView的其他行为,此技术将为您节省一些工作。

假设您的GUI逻辑由QMainWindow子类维护,并且QGraphicsView和QGraphicsScene被声明为该子类的私有成员。您将必须实现如下的eventFilter函数:

bool MyMainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == scene && event->type() == Event::GraphicsSceneMouseMove)
    {
        QGraphicsSceneMouseEvent *m = static_cast<QGraphicsSceneMouseEvent*>(event);
        if (m->buttons() & Qt::MiddleButton)
        {
            QPointF delta = m->lastScreenPos() - m->screenPos();
            int newX = view->horizontalScrollBar()->value() + delta.x();
            int newY = view->verticalScrollBar()->value() + delta.y();
            view->horizontalScrollBar()->setValue(newX);
            view->verticalScrollBar()->setValue(newY);
            return true;
        }
    }

    return QMainWindow::eventFilter(obj, event);
}
Run Code Online (Sandbox Code Playgroud)

要从QGraphicsScene过滤事件,您必须安装MyMainWindow作为场景的eventFilter。也许可以在设置GUI的同一功能中执行此操作。

void MyMainWindow::setupGUI()
{ 
    // along with other GUI stuff...

    scene->installEventFilter(this);
}
Run Code Online (Sandbox Code Playgroud)

您可以扩展这个想法,用拖动“手”代替光标,如上所示。