我创建了一个小型原型,其中包含QGraphicsView
我绑定到GraphicsScene
的{{1}}我可以添加或删除QGraphicsTextItem
。这是执行作业的cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QGraphicsTextItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QGraphicsScene* scene = new QGraphicsScene();
ui->graphicsView->setScene(scene);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(addGraphicsItem()));
connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(removeGraphicsItem()));
}
MainWindow::~MainWindow()
{
auto scene = ui->graphicsView->scene();
ui->graphicsView->setScene(nullptr);
delete scene;
delete ui;
}
void MainWindow::addGraphicsItem()
{
QGraphicsTextItem* item = new QGraphicsTextItem("jgfkdljkdj");
_items.push_back(item);
ui->graphicsView->scene()->addItem(_items.back());
}
void MainWindow::removeGraphicsItem()
{
auto item = _items.back();
ui->graphicsView->scene()->removeItem(item);
_items.erase(_items.end()-1);
delete item;
}
我无法理解在创建/删除场景和/或其基础项目时如何安全地管理我的记忆。阅读很多关于此问题的帖子,例如this one,我找到了一个代码,但我觉得它过于苛刻,而Qt可能会在没有它的情况下完成工作。当删除和删除场景中的一个项目时,这是否真的是在MainWindow::removeGraphicsItem
槽中实现的方式?删除场景时是MainWindow::~MainWindow
析构函数?
答案 0 :(得分:3)
最简单的方法是让语言和框架为你管理内存。
按值存储QGraphicsScene
,并利用场景是资源管理器的事实,与项目紧密耦合。它管理物品的使用寿命,并保证任何物品都不会超过现场,即它会处理在破坏者运行之前没有处理过的任何物品。
要从场景或父项中删除项目,只需将其删除即可。该项目将通知场景和任何父母即将消失,并且场景将从其项目列表中删除它。那就是QObject
内存管理的工作方式。
您可能还希望使用QGraphicsScene::items
或QGraphicsItemGroup::childItems
,而不是手动管理对象列表。使用手动列表需要注意将列表的内容与对象生存期同步。场景或项目组会自动执行此操作。
如果要写它,我会按如下方式进行。我还展示了如何在场景中混合不同的项目生命周期,以及如何按值保存项目。
// mainwindow.h
#pragma once
#include "ui_mainwindow.h"
#include <QGraphicsScene>
class MainWindow : public QMainWindow {
Q_OBJECT
Ui::MainWindow ui;
QGraphicsScene m_scene;
QGraphicsTextItem m_text{tr("foo")};
QGraphicsItemGroup m_dynamicItems;
template <typename T, typename ...Ar> T* newItem(Ar&&... args);
public:
MainWindow(QWidget *parent = {});
Q_SLOT void addItem();
Q_SLOT void removeItem();
Q_SLOT void removeAllItems();
};
// mainwindow.cpp
#include "mainwindow.h"
#include <utility>
template <typename T, typename ...Ar>
T* MainWindow::newItem(Ar&&... args) {
return new T{&this->m_dynamicItems, std::forward<Ar>(args)...};
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
ui.setupUi(this);
ui.graphicsView->setScene(&m_scene);
m_scene.addItem(&m_text);
m_scene.addItem(&m_dynamicItems);
auto const clicked = &QPushButton::clicked;
connect(ui.pushButton, clicked, this, &MainWindow::addItem);
connect(ui.pushButton2, clicked, this, &MainWindow::removeItem);
}
void MainWindow::addItem() {
newItem<QGraphicsTextItem>(tr("jfslkdfjd"));
}
void MainWindow::removeItem() {
auto const &items = std::as_const(m_dynamicItems.childItems());
if (!items.isEmpty())
delete items.back();
}
void MainWindow::removeAllItems() {
for (auto *item : std::as_const(m_dynamicItems.childItems()))
delete item;
// or (deprecated but you may run into such code)
qDeleteAll(std::as_const(m_dynamicItems.childItems()));
}