如何在 QGraphicsView 中平移图像

发布于 2024-10-13 18:27:03 字数 269 浏览 9 评论 0原文

我目前可以将图像加载到图形场景中,然后再次加载到 QGraphicsViewer 中。

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

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

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

I am currently able to load my image into a grahpics scene, and then again into a QGraphicsViewer.

I am able to implement a zoom feature by dtecting a QEvent::Wheel and then calling the graphicsViews's scale() function.

However, I can't seem to figure out how to get the pan functionality working. I basically want to detect when a mouse has clicked down on the image, and then move the image left, right, up or down along with the mouse.

As of right now, I basically have a MouseFilter class that is detecting events, and doing different things depending on the event type. I attached that listener to the QGraphicsView object

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我是男神闪亮亮 2024-10-20 18:27:03

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

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;
};

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

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();
}

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

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

实际上管理拖动,您需要覆盖鼠标移动事件。 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();

}

In case someone is wondering how to do it on their own, it's actually quite simple. Here's the code from my app:

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;
};

You need to store the start position of the drag, for example like this (I used the right button):

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();
}

Also, you need to clear the flag and restore the cursor once the button is released:

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

To actually manage the drag, you need to override the mouse move event. QGraphicsView inherits a QAbstractScrollArea, and its scrollbars are easily accessible. You also need to update the pan position:

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();

}
很快妥协 2024-10-20 18:27:03

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

QGraphicsView has build-in mouse-panning support. Set correct DragMode and it will handle the rest. You do need the enable scroll bars for that to work.

戴着白色围巾的女孩 2024-10-20 18:27:03

neuviemeporte 解决方案需要子类化 QGraphicsView。

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

假设您的 GUI 逻辑由 QMainWindow 子类和 QGraphicsView 和 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);
}

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

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

    scene->installEventFilter(this);
}

您可以扩展此想法,将光标替换为拖动“手”,如前所示。

neuviemeporte solution requires to subclass a QGraphicsView.

Another working drag implementation can be obtained without subclassing the view using eventFilter. If you don't need to customize other behaviors of the QGraphicsView, this technique will save you some work.

Let's say your GUI logic is maintained by a QMainWindow subclass and the QGraphicsView & QGraphicsScene are declared as a private members of this subclass. You would have to implement the eventFilter function as follows:

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);
}

To filter events from the QGraphicsScene, you'll have to install MyMainWindow as an eventFilter of the scene. Perhaps you could do this in the same function where you setup your GUI.

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

    scene->installEventFilter(this);
}

You can extend this idea to replace the cursor with the drag "hand" as previously shown.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文