Tag Archives: mouseMoveEvent

Dibujo en Qt. Parte II. Añadir un cursor crosshair


En la primera parte se ve como empezar a dibujar sobre un QGraphicsScene y mostrarlo en un QGraphicsView. A continuación vamos a añadir un cursor crosshair a la escena para que siga los movimientos del ratón.

1. Capturar los eventos del ratón.
Para detectar el movimiento del ratón sobre la escena se necesita crear una subclass del QGrahicsScene y redefinir la función mouseMoveEvent.

1.1 Una subclass de QGraphicsScene.
MyGraphScene.h

#ifndef MYGRAPHICSCENE_H
#define MYGRAPHICSCENE_H

#include <QGraphicsScene>

class MyGraphicScene2 : public QGrapicsScene
{
    Q_OBJECT
public:
    explicit MyGraphicScene2(QObject *parent = 0);

protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
signals:

public slots:

};

#endif // MYGRAPHICSCENE_H

MyGraphScene.cpp

#include "mygraphicscene2.h"

MyGraphicScene2::MyGraphicScene2(QObject *parent) :
    QGrapicsScene(parent)
{
}

void MyGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
}

2. El dibujo del cursor.
Declarar dos QGraphicsLineItem para dibujar la cruz y un QGraphicsTextItem para mostrar un mensaje de texto. El cursor tiene que mostrarse por encima de todo lo dibujado. Para eso se modifica la propiedad setZValue() de las lineas y el texto del cursor.

MyGrahicsScene.h

private:
    QPen pen;
    QGraphicsLineItem *horizHair;
    QGraphicsLineItem * vertHair;
    QGraphicsTextItem * cursorText;

MyGrapicsScene.cpp

MyGraphicsScene::MyGraphicsScene(QObject *parent) :
    QGraphicsScene(parent)
{
    cursorText = this->addText("");	//Inicializar el texto a mostrar sobre el cursor.
    cursorText->setZValue(100);		//Llevar por encima de todo el dibujo

    horizHair = this->addLine(-2000,0,2000,0,pen);	//Las líneas son lo suficiente largas para 
    vertHair = this->addLine(0,-1000,0,1000,pen);	//salir del borde de la pantalla.
    horizHair->setZValue(100);				
    vertHair->setZValue(100);
}

void MyGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
    //qDebug() << event->scenePos();
    // Mover las lineas a la posición del ratón.
    horizHair->setPos(event->scenePos());
    vertHair->setPos(event->scenePos());

    // Mostrar las coordenadas del ratón sobre el cursor.
    QString txt;
    txt = QString::number(event->scenePos().x()) + "," + QString::number(event->scenePos().y());
    cursorText->setPlainText(txt);
    cursorText->setPos(event->scenePos().x(), event->scenePos().y() -16);
}

3. Ocultar la flecha del ratón sobre la escena.
Hay que detectar cuando el ratón entra en la escena para ocultar la flecha del cursor. Así mismo, cuando sale hay que volver a mostrarlo. Atención que al pasar el ratón sobre las barras de scroll del QGraphicsView tiene que volver a mostrarse la flecha del cursor.

Para conseguir esto hay que redefinir
bool eventFilter(QObject *watched, QEvent *event);

MyGrahicsScene.h

protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);

MyGraphicsScene.cpp
En el constructor:

installEventFilter(this);

La función eventFilter:

bool MyGraphicsScene::eventFilter(QObject *watched, QEvent *event) {
    QGraphicsView *v;
    v = views().at(0);

    if(watched==this && (event->type()==QEvent::Enter || event->type()==QEvent::Leave)) {
        if (event->type() == QEvent::Enter) {
            qDebug() << "Hovering";
            v->setCursor(Qt::BlankCursor);
            horizHair->show();
            vertHair->show();
            cursorText->show();
        } else {
            qDebug() << "not Hovering";
            v->setCursor(Qt::ArrowCursor);
            horizHair->hide();
            vertHair->hide();
            cursorText->hide();
        }
    }
}