我创建了一个小原型,其中包含一个绑定到可以添加或删除QGraphicsTextItem的QGraphicsView的GraphicsScene。下面是完成这项工作的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析构函数时,真的是这样做的吗?
发布于 2018-03-14 00:16:43
最简单的做法是让语言和框架为您管理内存。
按值存储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()));
}https://stackoverflow.com/questions/49252695
复制相似问题