fol*_*bis 4 c++ qt qtgui qgraphicsitem qt5
为了调整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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这里是 的定义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;
}
}
Run Code Online (Sandbox Code Playgroud)
您说您的子项目没有收到鼠标事件,但它们确实收到了。您可以通过void mousePressEvent(QGraphicsSceneMouseEvent * event)向 Vertice 添加 a 并注意它被调用来验证这一点。
您的问题是 Qt 忽略了ItemIsMovable子 QGraphicsItem 上的标志。当你询问时它甚至没有设置标志。
您可以通过更改 Vertice 构造函数来验证这一点:
Vertice::Vertice(QGraphicsItem * parent) :
QGraphicsItem(parent)
{
setFlag(ItemIsMovable);
Q_ASSERT(flags() & ItemIsMovable); // fails
setFlag(ItemIsSelectable);
setFlag(ItemSendsGeometryChanges);
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样呢?正如编程绝地所说:“使用源代码,卢克!”
请注意,设置标志时它所做的事情之一是提供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;
}
}
Run Code Online (Sandbox Code Playgroud)
呃哦。无返回结果!将此行添加到末尾,就像您在项目中一样:
return QGraphicsItem::itemChange(change, value);
Run Code Online (Sandbox Code Playgroud)
...你就得到了它。其他注意事项:
“Vertices”的单数形式实际上是“Vertex”
如果您遇到这样的情况,请考虑将其从您正在编写的任何特定程序中删除。如果您可以用一个子项和一个父项来演示该问题,那么为什么要使用一个循环来生成四个呢?如果选择不是问题的一部分——并且不需要涉及隐藏和显示顶点的代码——那么为什么要涉及它呢?最好使用您提供的代码来提供所需的虚拟方法,而boundingRect()不是让其他人编写它来测试。请参阅简短、独立、可编译的示例
Qt 源代码具有相当的可读性并且组织良好,因此请养成查看它的习惯......!