Child items not movable in QGraphicsView when ItemIsMovable flag is set

三世轮回 提交于 2019-12-10 18:18:18

问题


To resize items in a QGraphicsView, I'm putting child items representing vertices onto the item to be moved (using the parent-child relationship established in the constructor). Those are the four blue circles in the picture below:

But the child vertices are not receiving mouse events. Only the parent item (red square) is getting mouse events.

Here is the definition for Item:

Item::Item(QGraphicsItem * parent) :
    QGraphicsItem(parent)
{
    setFlag(ItemIsMovable);
    setFlag(ItemIsSelectable);
    setFlag(ItemSendsGeometryChanges);
    setCacheMode(DeviceCoordinateCache);   
}

void Item::paint(
    QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->fillRect(option->rect,Qt::red);
}

QVariant Item::itemChange(GraphicsItemChange change, const QVariant & value)
{
    switch(change)
    {
        case QGraphicsItem::ItemSelectedHasChanged:
            qWarning() << "item: " + value.toString();
            updateVertices(value.toBool());
            break;
        default:
            break;
    }
    return QGraphicsItem::itemChange(change, value);
}

void Item::updateVertices(bool visible) {
    if(visible) {
        if(vertices.length() == 0) {
            for(int i = 0; i < 4; i++)
                vertices.append(new Vertice(this));
        } else
            for(int i = 0; i < 4; i++)
                vertices[i]->setVisible(true);

        QRectF rect = boundingRect();
        vertices[0]->setPos(rect.topLeft());
        vertices[1]->setPos(rect.topRight());
        vertices[2]->setPos(rect.bottomLeft());
        vertices[3]->setPos(rect.bottomRight());
    } else {
        for(int i = 0; i < 4; i++) {
            p_vertices[i]->setVisible(false);
        }
    }
}

While here is the definition for Vertice:

Vertice::Vertice(QGraphicsItem * parent) :
    QGraphicsItem(parent)
{
    setFlag(ItemIsMovable);
    setFlag(ItemIsSelectable);
    setFlag(ItemSendsGeometryChanges);
}

void Vertice::paint(
    QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setBrush(Qt::blue);
    painter->setPen(Qt::darkGray);
    painter->drawEllipse(-5,-5,10,10);
}

QVariant Vertice::itemChange(GraphicsItemChange change, const QVariant & value)
{
    switch(change) {
        case QGraphicsItem::ItemSelectedHasChanged:
            qWarning() << "vertex: " + value.toString(); // never happened
            break;
        default:
            break;
    }
}

回答1:


You say that your child items aren't getting mouse events, but they are. You can verify this by adding a void mousePressEvent(QGraphicsSceneMouseEvent * event) to Vertice and noticing that it is getting called.

Your problem is that Qt is ignoring the ItemIsMovable flag on a child QGraphicsItem. It's not even setting the flag when you ask.

You can verify this by changing your Vertice constructor:

Vertice::Vertice(QGraphicsItem * parent) :
    QGraphicsItem(parent)
{
    setFlag(ItemIsMovable);
    Q_ASSERT(flags() & ItemIsMovable); // fails
    setFlag(ItemIsSelectable);
    setFlag(ItemSendsGeometryChanges);
}

Now why would that be? As the programming Jedi say: "use the source, Luke!"

https://qt.gitorious.org/qt/qtbase/source/7df3321f934e5bd618e2ad00bf801f2b7edd31df:src/widgets/graphicsview/qgraphicsitem.cpp#L1789

Notice that one of the things it does when flags are set is it offers that to itemChange to inspect with an ItemFlagsChange notification. Not only that, but it allows the flags to be overwritten by the result of that call. But look at your implementation of itemChange() on Vertice:

QVariant Vertice::itemChange(GraphicsItemChange change, const QVariant & value)
{
    switch(change) {
        case QGraphicsItem::ItemSelectedHasChanged:
            qWarning() << "vertex: " + value.toString(); // never happened
            break;
        default:
            break;
    }
}

Uh-oh. No return result! Add this line to the end, as you have in your Item:

return QGraphicsItem::itemChange(change, value);

...and there you have it. Other notes:

  • Singular of "Vertices" is actually "Vertex"

  • If you have a case like this, think about paring it down from whatever specific program you are writing. If you can demonstrate the problem with one child item and one parent item, then why have a loop making four? If selection isn't part of the problem--and code for hiding and showing vertices need not be involved--then why involve it? It would be much better to use the code you provide to give required virtual methods like boundingRect() rather than make others write it to test. See Short, Self-Contained, Compilable Example

  • Qt source is fairly readable and well-organized, so do get into the habit of looking at it...!



来源:https://stackoverflow.com/questions/21745025/child-items-not-movable-in-qgraphicsview-when-itemismovable-flag-is-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!