C++ QGraphicsSiteMgroup::boundingRect()未更新

C++ QGraphicsSiteMgroup::boundingRect()未更新,c++,qt,qgraphicsview,qgraphicsscene,qgraphicsitem,C++,Qt,Qgraphicsview,Qgraphicsscene,Qgraphicsitem,我一直在尝试使用QGraphicsItemGroup来获取一组QGraphicsItem*s的边界矩形。在我看来,当我将所有项目插入到组中时,边界矩形是正确确定的;但是,如果我随后移动组中的项目,则边界矩形不会像我预期的那样更新以包含移动的项目。我在文档中找不到关于我所看到的行为是否正确的指示;我猜我要么误解了QGraphicsSiteMgroup的工作原理,要么误用了它 我用来测试的一个例子: #include "mainwindow.h" #include "ui_mainwindow.h"

我一直在尝试使用QGraphicsItemGroup来获取一组QGraphicsItem*s的边界矩形。在我看来,当我将所有项目插入到组中时,边界矩形是正确确定的;但是,如果我随后移动组中的项目,则边界矩形不会像我预期的那样更新以包含移动的项目。我在文档中找不到关于我所看到的行为是否正确的指示;我猜我要么误解了QGraphicsSiteMgroup的工作原理,要么误用了它

我用来测试的一个例子:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QTransform>
#include <QGraphicsEllipseItem>
#include <QDebug>
#include <QTimer>

#include <cmath>

const double pi = 3.14;

QTransform rotation(double degrees)
{

    double a    = pi/180 * degrees;
    double sina = sin(a);
    double cosa = cos(a);

    return QTransform(cosa, sina, -sina, cosa, 0, 0);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();

    //Shouldn't execute until after window.show() and application.exec()
    //are called
    QTimer::singleShot(1, this, &MainWindow::build);
}

void MainWindow::build()
{
    QGraphicsEllipseItem* el1 = scene->addEllipse(-5, -5, 10, 10);
    scene->addLine(0, 0, 0, 10)->setParentItem(el1);

    QGraphicsEllipseItem* el2 = scene->addEllipse(-5, -5, 10, 10);
    scene->addLine(0, 0, 0, 10)->setParentItem(el2);

    QGraphicsEllipseItem* el3 = scene->addEllipse(-5, -5, 10, 10);
    scene->addLine(0, 0, 0, 10)->setParentItem(el3);

    QGraphicsEllipseItem* el4 = scene->addEllipse(-5, -5, 10, 10);
    scene->addLine(0, 0, 0, 10)->setParentItem(el4);

    QGraphicsItemGroup* group = new QGraphicsItemGroup;
    group->addToGroup(el1);
    group->addToGroup(el2);
    group->addToGroup(el3);
    group->addToGroup(el4);

    scene->addItem(group);

    scene->addRect(group->boundingRect());

    QTransform translate2(1, 0, 0, 1, 10, 10);
    QTransform t2 = /*rotation(45) **/ translate2;
    el2->setTransform(t2);

    QTransform translate3(1, 0, 0, 1, 20, 20);
    QTransform t3 = /*rotation(-45) **/ translate3 * t2;
    el3->setTransform(t3);

    QTransform translate4(1, 0, 0, 1, 20, -20);
    QTransform t4 = translate4 * t3;
    el4->setTransform(t4);

    qDebug() << t4.dx() << t4.dy() << atan2(t4.m12(), t4.m22())*180/pi;
    QTransform t4i = t4.inverted();
    qDebug() << t4i.dx() << t4i.dy() << atan2(t4i.m12(), t4i.m22())*180/pi;

    scene->addRect(group->boundingRect());
}

MainWindow::~MainWindow()
{
    delete ui;
}
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括
#包括
#包括
#包括
#包括
常数双pi=3.14;
Q变换旋转(双度)
{
双a=pi/180*度;
双新浪=罪恶(a);
双cosa=cos(a);
返回QTransform(cosa,sina,-sina,cosa,0,0);
}
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
场景=新的Qgraphicscene(此);
ui->graphicsView->setScene(场景);
用户界面->图形视图->显示();
//在window.show()和application.exec()之后才应执行
//被称为
QTimer::singleShot(1,this,&MainWindow::build);
}
void MainWindow::build()
{
QGraphicsEllipseItem*el1=场景->加法器(-5,-5,10,10);
场景->添加行(0,0,0,10)->setParentItem(el1);
QGraphicsEllipseItem*el2=场景->加法器(-5,-5,10,10);
场景->添加行(0,0,0,10)->setParentItem(el2);
QGraphicsEllipseItem*el3=场景->加法器(-5,-5,10,10);
场景->添加行(0,0,0,10)->setParentItem(el3);
QGraphicsEllipseItem*el4=场景->加法器(-5,-5,10,10);
场景->添加行(0,0,0,10)->setParentItem(el4);
QGraphicsSiteMgroup*组=新的QGraphicsSiteMgroup;
组->添加组(el1);
组->添加组(el2);
组->添加组(el3);
组->添加组(el4);
场景->添加项(组);
场景->添加矩形(组->边界矩形());
转化翻译体2(1,0,0,1,10,10);
qtransformt2=/*旋转(45)**/平移2;
el2->setTransform(t2);
QT转化translate3(1,0,0,1,20,20);
QTransform t3=/*旋转(-45)**/平移3*t2;
el3->setTransform(t3);
QT转化翻译4(1,0,0,1,20,-20);
QTransform t4=translate4*t3;
el4->setTransform(t4);

qDebug()QGraphicsItemGroup
文档似乎没有提到这一点,但它只是在显示视图和
qgraphicscene
后重新计算
QGraphicsItemGroup
boundingRect

之后添加项目

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView mainView(&scene);
    scene.setSceneRect(0, 0, 800, 800);

    QGraphicsEllipseItem* el1 = scene.addEllipse(-5, -5, 10, 10);
    scene.addLine(0, 0, 0, 10)->setParentItem(el1);

    QGraphicsEllipseItem* el2 = scene.addEllipse(-5, -5, 10, 10);
    scene.addLine(0, 0, 0, 10)->setParentItem(el2);

    QGraphicsEllipseItem* el3 = scene.addEllipse(-5, -5, 10, 10);
    scene.addLine(0, 0, 0, 10)->setParentItem(el3);

    QGraphicsEllipseItem* el4 = scene.addEllipse(-5, -5, 10, 10);
    scene.addLine(0, 0, 0, 10)->setParentItem(el4);

    QGraphicsItemGroup* group = new QGraphicsItemGroup;
    scene.addItem(group);


    QTransform translate2(1, 0, 0, 1, 10, 10);
    QTransform t2 = /*rotation(45) **/ translate2;
    el2->setTransform(t2);

    QTransform translate3(1, 0, 0, 1, 20, 20);
    QTransform t3 = /*rotation(-45) **/ translate3 * t2;
    el3->setTransform(t3);

    QTransform translate4(1, 0, 0, 1, 20, -20);
    QTransform t4 = translate4 * t3;
    el4->setTransform(t4);

    mainView.show();

    group->addToGroup(el1);
    group->addToGroup(el2);
    group->addToGroup(el3);
    group->addToGroup(el4);
    scene.addRect(group->boundingRect());
    qDebug() << group->sceneBoundingRect() << endl << group->boundingRect();
    scene.addRect(group->sceneBoundingRect());

    return a.exec();
}
intmain(intargc,char*argv[])
{
质量保证申请a(argc、argv);
QsCENE场景;
QGraphicsView主视图(和场景);
场景设置(0,0,800,800);
QGraphicsEllipseItem*el1=场景.加法(-5,-5,10,10);
addLine(0,0,0,10)->setParentItem(el1);
QGraphicsEllipseItem*el2=场景.加法(-5,-5,10,10);
addLine(0,0,0,10)->setParentItem(el2);
QGraphicsEllipseItem*el3=场景.加法(-5,-5,10,10);
addLine(0,0,0,10)->setParentItem(el3);
QGraphicsEllipseItem*el4=场景.加法(-5,-5,10,10);
addLine(0,0,0,10)->setParentItem(el4);
QGraphicsSiteMgroup*组=新的QGraphicsSiteMgroup;
情景补充(组);
转化翻译体2(1,0,0,1,10,10);
qtransformt2=/*旋转(45)**/平移2;
el2->setTransform(t2);
QT转化translate3(1,0,0,1,20,20);
QTransform t3=/*旋转(-45)**/平移3*t2;
el3->setTransform(t3);
QT转化翻译4(1,0,0,1,20,-20);
QTransform t4=translate4*t3;
el4->setTransform(t4);
mainView.show();
组->添加组(el1);
组->添加组(el2);
组->添加组(el3);
组->添加组(el4);
scene.addRect(group->boundingRect());
qDebug()scenebounddirect()scenebounddirect());
返回a.exec();
}
结果是组中所有成员的边界矩形


boundingrect仅在添加项时更新。因此必须使用方法
childrenBoundingRect()
,而不是boundingrect()。 在QGraphicsItemGroup的一个单独的子类中,比如MyQGraphicsItemGroup,我们可以重载方法
virtualqrectf boundingRect()const override
,以便调用
childrenBoundingRect()

QRectF MyQGraphicsItemGroup::boundingRect() const
{
   // must be overloaded, otherwise the boundingrect will only be actualized on
   // additem is actualized. This leads to the fact that the boundingrect 
   // will not close around the word items after e.g., moving them. 
   return childrenBoundingRect();
}

有趣的是,这里MainView的上下文是什么?我将我的QGraphicsViewWidget作为MainWindow的子项;使用Qt Form.ui文件创建。即使经过调整,所有内容都添加到MainWindow.show()之后,这不是我看到的。当QGraphicsView有一个父窗口小部件时,行为会有所不同吗?好的,我必须进行一些实验;我的猜测是,当ViewWidget不是顶级对象时,不会调用show();所以可能会有不同的初始化方式吗?我发现childrenBoundingRect()做我想做的;这一个遍历GraphicsItem的所有decent并结合它们的边界。不幸的是,当rect改变时,它不会被存储;因此它是对每次子代数的线性运算。好消息是,我的项目都没有超过10个子代