【问题标题】:Child items not movable in QGraphicsView when ItemIsMovable flag is set设置 ItemIsMovable 标志时,子项在 QGraphicsView 中不可移动
【发布时间】:2014-03-11 18:53:55
【问题描述】:

为了调整QGraphicsView 中的项目大小,我将表示顶点的子项目放在要移动的项目上(使用构造函数中建立的父子关系)。就是下图中的四个蓝色圆圈:

但是子顶点没有接收到鼠标事件。只有父项(红色方块)正在获取鼠标事件。

这是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);
        }
    }
}

这里是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;
    }
}

【问题讨论】:

  • 那么您遇到的问题是什么?

标签: c++ qt qt5 qgraphicsitem qtgui


【解决方案1】:

您说您的子项没有获得鼠标事件,但它们是。您可以通过将 void mousePressEvent(QGraphicsSceneMouseEvent * event) 添加到 Vertice 并注意到它正在被调用来验证这一点。

您的问题是 Qt 忽略了子 QGraphicsItem 上的 ItemIsMovable 标志。当您询问时,它甚至没有设置标志。

您可以通过更改 Vertice 构造函数来验证这一点:

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

现在为什么会这样?正如编程绝地所说:“使用源代码,卢克!”

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

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

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

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

return QGraphicsItem::itemChange(change, value);

...你有它。其他说明:

  • “顶点”的单数 is actually "Vertex"

  • 如果您有这样的情况,请考虑从您正在编写的任何特定程序中削减它。如果您可以用一个子项和一个父项来演示问题,那么为什么要循环生成四个?如果选择不是问题的一部分——并且不需要涉及隐藏和显示顶点的代码——那么为什么要涉及它呢?最好使用您提供的代码来提供所需的虚拟方法,例如boundingRect(),而不是让其他人编写它来测试。见Short, Self-Contained, Compilable Example

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

【讨论】:

  • 谢谢你,@HostileFork 为你提供了有用的答案,也为你提供了戒律)我对文档中的这一行感到失望:QGraphicsItem::ItemSelectedHasChanged 项目的选定状态已更改。 value 参数是新的选定状态(即,真或假)。在传递此通知时不要在 itemChange() 中调用 setSelected()。 忽略返回值
  • @folibis 很高兴为您提供帮助。我同意这是具有误导性的,至少如果有人有机会强调,那是错误的强调。 I filed a documentation bug 为它。
猜你喜欢
  • 1970-01-01
  • 2011-06-22
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
相关资源
最近更新 更多