QMouseMoveEvent和QKeyEvent修饰符出现意外行为



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

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

  2. 按下controll和不按下controll都可以移动,但当我在按下controll的同时停止移动并继续使用鼠标滚轮时,不仅会调用mousemoveevent,而且controlmodifier仍然处于活动状态。问题出在哪里?

main.cpp

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

这真的很奇怪。QGraphicsSceneMouseEvent::modifiers返回的Qt::KeyboardModifiers状态似乎只有在鼠标实际移动时才会更新。更奇怪的是,在您的代码中,QGraphicsSceneMouseMove类型的QgraphicsSceneMhouseMove事件会被发送,即使鼠标根本没有移动,但只有轮子转动。也许由于缩放而导致的相对移动算作移动,但不算作移动,这会更新修改器。

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

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

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()在按下或释放控制键时会立即更新。

相关内容

  • 没有找到相关文章

最新更新