设置 ItemIsMovable 标志时,QGraphicsView 中的子项不可移动 [英] Child items not movable in QGraphicsView when ItemIsMovable flag is set

查看:132
本文介绍了设置 ItemIsMovable 标志时,QGraphicsView 中的子项不可移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在

请注意,设置标志时它所做的一件事是它提供给 itemChange 以使用 ItemFlagsChange 通知进行检查.不仅如此,它还允许标志被该调用的结果覆盖.但是看看你在 Vertice 上的 itemChange() 实现:

QVariant Vertice::itemChange(GraphicsItemChange change, const QVariant & value){开关(改变){案例 QGraphicsItem::ItemSelectedHasChanged:qWarning() <<顶点:" + value.toString();//从来没有发生过休息;默认:休息;}}

呃-哦.没有返回结果!将此行添加到末尾,就像在您的项目中一样:

return QGraphicsItem::itemChange(change, value);

...你有它.其他注意事项:

  • 顶点"的单数实际上是顶点"

  • 如果您有这样的案例,请考虑将其从您正在编写的任何特定程序中删除.如果你可以用一个子项和一个父项来演示这个问题,那么为什么要循环制作四个呢?如果选择不是问题的一部分——并且不需要涉及隐藏和显示顶点的代码——那么为什么要涉及它呢?最好使用您提供的代码来提供所需的虚拟方法,例如 boundingRect(),而不是让其他人编写它来进行测试.请参阅简短、自包含、可编译的示例

  • Qt 源代码可读性强且组织良好,因此请养成查看它的习惯...!

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

解决方案

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...!

这篇关于设置 ItemIsMovable 标志时,QGraphicsView 中的子项不可移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆