1

我在代码中遇到意外行为。我有一个包含 QGraphicsScene 的 QGraphicsView。现在我想检测用于缩放视图的鼠标滚轮和用于移动场景中项目的鼠标移动,后者仅在按下 controll 时。现在我有两个问题:

  1. 即使鼠标没有移动而只移动鼠标滚轮,也会调用 MouseMoveEvent。

  2. 在按下和不按下控件的情况下移动都可以正常工作,但是当我在按下控件时停止移动并继续使用鼠标滚轮时,不仅调用了 mousemoveevent,而且 controllmodifier 仍然处于活动状态。问题是什么?

主文件

#include "ppi.h"
#include <QtGui/QApplication>

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

ppi.h

#ifndef PPI_H
#define PPI_H

#include <QtGui/QMainWindow>
#include <QGraphicsView>
#include <QDebug>
#include <QWheelEvent>

#include "ui_ppi.h"
#include "ppiView.h"
#include "ppiscene.h"

class PPI : public QMainWindow
{
    Q_OBJECT

public:
    PPI(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~PPI();
    int i;

private:
    Ui::ppiClass ui;
    PPIScene* ppiScene;

protected slots:
    void onZoom(QWheelEvent *event);
    void onMouseMoved(QGraphicsSceneMouseEvent *event);
};

#endif // PPI_H

ppi.cpp

#include "ppi.h"


PPI::PPI(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
    ui.setupUi(this);

    ppiScene = new PPIScene(this);

    connect(ppiScene, SIGNAL(mouseMoved(QGraphicsSceneMouseEvent*)), this, SLOT(onMouseMoved(QGraphicsSceneMouseEvent*)));
    connect(ui.gVPPI, SIGNAL(zoom(QWheelEvent*)), this, SLOT(onZoom(QWheelEvent*)));

    ppiScene->setSceneRect(0,0,1024,1024);
    ui.gVPPI->setScene(ppiScene);
    ui.gVPPI->setMouseTracking(true);

    i = 0;
}

PPI::~PPI()
{

}



void PPI::onZoom(QWheelEvent *event)
{
        if(event->delta() > 0)
            ui.gVPPI->scale(1.01, 1.01);
        else
            ui.gVPPI->scale(1/1.01, 1/1.01);
}


void PPI::onMouseMoved(QGraphicsSceneMouseEvent *event)
{
    i++;
    qDebug() << "slot" << i << event->modifiers();
    if(event->modifiers() & Qt::ControlModifier)
    {
        qDebug() << "ctrl pressed";
    }
}

ppiview.h

#ifndef PPIVIEW_H
#define PPIVIEW_H

#include <QGraphicsView>
#include <QMouseEvent>

class PPIView : public QGraphicsView
{
    Q_OBJECT

public:
    PPIView(QWidget * parent = 0);
    ~PPIView();

private:
    void wheelEvent(QWheelEvent *event);

signals:
    void zoom(QWheelEvent *event);

};

#endif // PPIVIEW_H

ppiview.cpp

#include "ppiview.h"

PPIView::PPIView(QWidget * parent)
    : QGraphicsView(parent)
{

}

PPIView::~PPIView()
{

}

void PPIView::wheelEvent(QWheelEvent *event)
{
    emit zoom(event);
}

ppiscene.h

#ifndef PPISCENE_H
#define PPISCENE_H

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>

class PPIScene : public QGraphicsScene
{
    Q_OBJECT

public:
    PPIScene(QObject *parent);
    ~PPIScene();
    int i;

private:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

signals:
    void mouseMoved(QGraphicsSceneMouseEvent *event);

};

#endif // PPISCENE_H

ppiscene.cpp

#include "ppiscene.h"

PPIScene::PPIScene(QObject *parent)
    : QGraphicsScene(parent)
{
    i = 0;
}

PPIScene::~PPIScene()
{

}

void PPIScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    i++;
    qDebug() << "signal" << i << event->modifiers();
    emit mouseMoved(event);
}
4

1 回答 1

1

这真的很奇怪。看起来 QGraphicsSceneMouseEvent::modifiers 返回的 Qt::KeyboardModifiers 状态仅在鼠标物理移动时才更新。更奇怪的是,在你的代码中,QGraphicsSceneMouseMove 类型的 QGraphicsSceneMouseEvents 被发送,即使鼠标根本没有移动,而只是转动了滚轮。也许由于您的缩放而导致的相对移动算作移动,但不算作移动,它会更新修改器。

我能够重现您的问题:除非物理移动鼠标,否则修改器的状态不会改变。

幸运的是,有一个简单的解决方法。在

void PPI::onMouseMoved(QGraphicsSceneMouseEvent *event)
{
    i++;
    qDebug() << "slot" << i << event->modifiers();
    if(event->modifiers() & Qt::ControlModifier)
    {
        qDebug() << "ctrl pressed";
    }
}

代替:

if(event->modifiers() & Qt::ControlModifier)

和:

if(QApplication::queryKeyboardModifiers() & Qt::ControlModifier)

当您按下或释放控制键时,QApplication::queryKeyboardModifiers() 会立即更新。

于 2015-11-04T17:40:19.487 回答