嵌套QGraphicsScenes中的选择排除

问题描述

我有一个包含项目的QGraphicsScene(我们称之为母场景),其中一些还包含一个QGraphicsScene(我们将它们称为子场景)。

观察:子场景和母场景中的选择不会互相干扰。这意味着,如果我在母场景中选择一个项目,则可以在子场景中选择一个项目,而母场景中的项目将保持选中状态。

我的预期结果:我希望在一个场景中进行选择以清除其他任何场景中的选择。

[为清晰起见,进行编辑]当我在一个场景中选择一个项目时,我想取消选择其他场景中的所选项目,而不是在不同场景中具有多个焦点。

我的动力:我想这样做是因为当我使用键盘快捷键时,我不知道Qt将选择哪个场景。当我只有一个女儿时,就选择了母亲(我希望女儿)。

到目前为止我的解决方案:在子场景容器项中,mousepressEvent清除了母场景的选择。我发现此解决方案非常丑陋,我想知道是否有人知道使用某些内部Qt功能的更好解决方案。现在,它看起来像一个糟糕的DIY解决方案,将会带来很多问题。

提前谢谢!

[编辑:最小示例] 在此示例中,我们可以同时选择两个嵌套元素。我宁愿整个场景中一次只能选择一个

#include <QApplication>
#include <QGraphicsView>

#include <QGraphicsScene>
#include <QMainWindow>
#include <QGraphicsItem>
#include <QGraphicslinearLayout>
#include <QGraphicsWidget>
#include <QGraphicsProxyWidget>

// Item that gets red contour when selected
class SimpleItem : public QGraphicsItem
{
public :
    SimpleItem():QGraphicsItem()
    {
        setFlag(QGraphicsItem::ItemIsSelectable,true);
    }

    QRectF boundingRect() const override { return QRectF(-20,-20,40,40);}

    void paint(QPainter *painter,const qstyleOptionGraphicsItem *,QWidget *) override
    {
        painter->setPen(Qt::black);
        if(isSelected())
            painter->setPen(Qt::red);
        painter->setBrush(Qt::gray);
        painter->drawRect(boundingRect());
    }
};

// Item that contains a QGraphicsScene in a layout
// This item gets also a red contour when selected
class SceneItem : public QGraphicsWidget
{
public :
    SceneItem():QGraphicsWidget()
    {
        setFlag(QGraphicsItem::ItemIsSelectable,true);
        setFocusPolicy(Qt::ClickFocus);

        // Create the inner scene
        QGraphicslinearLayout * layout = new QGraphicslinearLayout;
        setLayout(layout);
        QGraphicsScene * scene = new QGraphicsScene;
        QGraphicsView * view = new QGraphicsView(scene);
        QGraphicsProxyWidget * proxy = new QGraphicsProxyWidget;
        layout->addItem(proxy);
        proxy->setWidget(view);

        // Add a simple item
        SimpleItem * simpleItem = new SimpleItem;
        scene->addItem(simpleItem);
    }

    QRectF boundingRect() const override { return QRectF(0,100,100);}

    void paint(QPainter *painter,QWidget *) override
    {
        painter->setPen(Qt::black);
        if(isSelected())
            painter->setPen(Qt::red);
        painter->setBrush(Qt::lightGray);
        painter->drawRect(boundingRect());
    }
};

// Main
int main(int argc,char *argv[])
{
    QApplication a(argc,argv);
    QMainWindow w;

    QGraphicsScene * scene = new QGraphicsScene;
    QGraphicsView * view = new QGraphicsView(scene);
    view->setDragMode(QGraphicsView::RubberBandDrag);
    w.setCentralWidget(view);

    SceneItem * item = new SceneItem;
    scene->addItem(item);

    w.show();

    return a.exec();
}

解决方法

Disclamer

我个人不建议将小部件嵌入QGraphicsScene:

“图形视图”高性能的关键在于减少每帧绘制的数量。 QGraphicsWidget和QGraphicsProxyWidget一起是巨大的性能杀手,因为它们不能以有效的方式呈现。

此引用的来源以及有关该主题的更多信息可在此博客文章中找到:

Should you still be using QGraphicsView?

解决方案

如果我必须不惜一切代价使用OP使用的确切方法,我的解决方案将是:

  1. 使用QGraphicsScene::selectionChanged对选择更改做出反应,并且
  2. 使用QGraphicsScene::selectedItems检查是否选择了一项。

示例

这是OP提供的MVCE,我对它进行了修改,以演示如何实现建议的解决方案:

MyWindow.Window_Closing