QGraphicsItemGroup::boundingRect() 未更新
QGraphicsItemGroup::boundingRect() not updating
我一直在尝试使用 QGraphicsItemGroup 来获取一组 QGraphicsItem*s 的边界矩形。在我看来,当我将所有项目插入组中时,边界矩形已正确确定;但是如果我随后移动组中的项目,边界矩形不会像我预期的那样更新以包含移动的项目。我在文档中找不到关于我所看到的行为是否正确的指示;我的猜测是我误解了 QGraphicsItemGroup 的工作原理或滥用它
我一直用来测试的一个例子:
#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;
}
最终显示的场景是这样的
实际结果
但是,我期待这样的结果,第一个 boundingRect 有一个小盒子,第二个有一个更大的盒子
预期结果
我是不是误解了 QGraphicsItemGroup 的工作原理,还是我使用不当?
Qt 版本:5.10
OS: Ubuntu 16.04
编译器 GCC 5.4
QGraphicsItemGroup
文档似乎没有提到这一点,但它只在视图和 QGraphicsScene
显示后重新计算 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();
}
组内所有成员的边界矩形结果
boundingrect 仅在 additem 处更新。因此必须使用方法 childrenBoundingRect()
而不是 boundingRect()。
在 QGraphicsItemGroup 的单独子类中,比如 MyQGraphicsItemGroup,我们可以重载方法 virtual QRectF 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();
}
我一直在尝试使用 QGraphicsItemGroup 来获取一组 QGraphicsItem*s 的边界矩形。在我看来,当我将所有项目插入组中时,边界矩形已正确确定;但是如果我随后移动组中的项目,边界矩形不会像我预期的那样更新以包含移动的项目。我在文档中找不到关于我所看到的行为是否正确的指示;我的猜测是我误解了 QGraphicsItemGroup 的工作原理或滥用它
我一直用来测试的一个例子:
#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;
}
最终显示的场景是这样的
实际结果
但是,我期待这样的结果,第一个 boundingRect 有一个小盒子,第二个有一个更大的盒子
预期结果
我是不是误解了 QGraphicsItemGroup 的工作原理,还是我使用不当?
Qt 版本:5.10
OS: Ubuntu 16.04
编译器 GCC 5.4
QGraphicsItemGroup
文档似乎没有提到这一点,但它只在视图和 QGraphicsScene
显示后重新计算 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();
}
组内所有成员的边界矩形结果
boundingrect 仅在 additem 处更新。因此必须使用方法 childrenBoundingRect()
而不是 boundingRect()。
在 QGraphicsItemGroup 的单独子类中,比如 MyQGraphicsItemGroup,我们可以重载方法 virtual QRectF 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();
}