首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正确删除QGraphicsScene

正确删除QGraphicsScene
EN

Stack Overflow用户
提问于 2018-03-13 17:37:14
回答 1查看 158关注 0票数 0

我创建了一个小原型,其中包含一个绑定到可以添加或删除QGraphicsTextItemQGraphicsViewGraphicsScene。下面是完成这项工作的cpp文件

代码语言:javascript
复制
#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析构函数时,真的是这样做的吗?

EN

回答 1

Stack Overflow用户

发布于 2018-03-14 00:16:43

最简单的做法是让语言和框架为您管理内存。

按值存储QGraphicsScene,并利用场景是资源管理器这一事实,与项紧密耦合。它管理项目的生命周期,并保证没有项目会超过场景,也就是说,它将负责处理在其析构函数运行之前未被处置的任何项目。

要从场景或父项目中删除项目,只需删除它即可。该项目将通知场景和所有父级它即将消失,并且场景将从其项目列表中删除该项目。这也是QObject内存管理的工作方式。

您可能还希望使用QGraphicsScene::itemsQGraphicsItemGroup::childItems,而不是手动管理对象列表。使用手动列表需要注意将列表的内容与对象生存期同步。场景或项目组会自动执行此操作。

如果我要写它,我会这样做。我还展示了如何在场景中混合不同的项目生命周期,以及如何按值持有项目。

代码语言:javascript
复制
// 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()));
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49252695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档