[Qt-interest] Lag of events and improper handling of mouse release when using QGraphicsItem::ItemIsMovable

Sherif Ghali sherif.ghali.1 at gmail.com
Sat Oct 29 17:32:01 CEST 2011


There sometimes seems to be issues with QGraphicsScene efficiency even
when the scene is trivial. The triangle in the following program is
controlled by its nodes. While dragging one node there is a visible
lag between the triangle edges and the node. The lag is disconcerting
since the code does essentially nothing yet.

Another problem is visible if you drag quickly then release the mouse.
The dragged node will no longer coincide with a triangle vertex. This
is the typical case of needing to handle not just mouse moves but also
mouse releases. Yet in this case using either
    QGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
or
    QGraphicsItem::mouseReleaseEvent (QGraphicsSceneMouseEvent *)
would defeat the use of
    QGraphicsItem::setFlags(QGraphicsItem::ItemIsMovable).

If there is a deficiency in this code and you see either how to
eliminate the lag or the proper way for handling mouse release events,
please comment.

Sherif


// main.cpp
#include "MyGraphicsScene.h"
#include <QtGui>

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);
    MyGraphicsScene * scene = new MyGraphicsScene;
    QGraphicsView * view = new QGraphicsView(scene);
    view->scale(1, -1);
    view->fitInView(scene->sceneRect() , Qt::KeepAspectRatio);
    view->setRenderHint(QPainter::Antialiasing);
    view->show();
    return app.exec();
}

// MyGraphicsScene.h
#ifndef MYGRAPHICSSCENE_H
#define MYGRAPHICSSCENE_H

#include "Node.h"
#include <QtGui>

class MyGraphicsScene : public QGraphicsScene
{
    Q_OBJECT;
public:
    MyGraphicsScene()
    {
        setSceneRect(QRectF(QPointF(-4,-4), QSizeF(8,8)));

        // Lines (Segments)
        z01 = insert_line();
        z12 = insert_line();
        z20 = insert_line();

        // Nodes
        ez0 = insert_node(QPointF( -0.5, 0.0));
        ez1 = insert_node(QPointF(  0.0, 1.0));
        ez2 = insert_node(QPointF(  0.5, 0.0));

        control_point_has_moved();
    }
private:
    QGraphicsLineItem * insert_line()
    {
        QGraphicsLineItem * line_item = new QGraphicsLineItem;
        line_item->setPen(QPen(Qt::black));
        line_item->setZValue(0.0);
        addItem(line_item);
        return line_item;
    }

    Node * insert_node(const QPointF & pos)
    {
        Node * n = new Node(pos);
        addItem(n);
        return n;
    }

public:
    void control_point_has_moved(QGraphicsEllipseItem * /*moved_node*/ = 0)
    {
        // We ignore here the optimization of selecting the two
relevant lines out of three.
        z01->setLine(QLineF(ez0->pos(), ez1->pos()));
        z12->setLine(QLineF(ez1->pos(), ez2->pos()));
        z20->setLine(QLineF(ez2->pos(), ez0->pos()));
        update();
    }

private:
    QGraphicsEllipseItem *ez0, *ez1, *ez2;
    QGraphicsLineItem *z01, *z12, *z20;
};

#endif // MYGRAPHICSSCENE_H

// Node.h
#ifndef NODE_H
#define NODE_H

#include <QtGui>

class Node : public QGraphicsEllipseItem
{
public:
    Node(const QPointF & p);

protected:
    virtual QVariant itemChange(GraphicsItemChange change, const
QVariant & value);
};

#endif // NODE_H

// Node.cpp
#include "Node.h"
#include "MyGraphicsScene.h"

const qreal radius = 0.10;

Node::Node(const QPointF & p)
    : QGraphicsEllipseItem(-radius, -radius, 2.0*radius, 2.0*radius)
{
    this->setPos(p);
    setFlags(QGraphicsItem::ItemIsMovable);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges);

    setBrush(Qt::green);
    setZValue(1.0);
}

QVariant Node::itemChange(GraphicsItemChange change, const QVariant & value)
{
    // Use neither ItemScenePositionHasChanged nor ItemPositionHasChanged, but:
    if(change == QGraphicsItem::ItemPositionChange) {
        QPointF newPos = value.toPointF(); // value is the new
position; no need to mapToScene
        dynamic_cast<MyGraphicsScene *>(scene())->control_point_has_moved(this);
    }

    return QGraphicsItem::itemChange(change, value);
}

# Project file

TEMPLATE = app
TARGET =
DEPENDPATH  += .
INCLUDEPATH += .

HEADERS += Node.h MyGraphicsScene.h
SOURCES += Node.cpp main.cpp



More information about the Qt-interest-old mailing list