QFileSystemModel 对象是否会被删除?

Do QFileSystemModel objects ever get deleted?

本文关键字:删除 对象 是否 QFileSystemModel      更新时间:2023-10-16

我有一个经典的QDialog,它用QFileSystemModel填充QTreeView,并具有过滤和处理用户选择项目列表的功能。我完全是C++和Qt新手,所以我一直在关注许多在线教程和示例。代码最终看起来像这样 [内容为简洁起见进行了匿名和编辑]:

在头文件中:

class MyExampleDialog : public QDialog
{
Q_OBJECT
public:
explicit MyExampleDialog(MyMainWidget *parent = nullptr);
~MyExampleDialog();
public slots:
virtual void accept() override;
private slots:
void directoryPathEntered();
void checkDirectoryPathAndUpdateTree(const QString& pathToCheck);
void validateSelection();
private:
QString getDirectoryPath() const;
QStringList updateFileSelection();
Ui::MyExampleDialog *_ui;
};

在源文件中:

MyExampleDialog::MyExampleDialog(MyMainWidget *parent) :
QDialog(parent),
_ui(new Ui::MyExampleDialog)
{
_ui->setupUi(this);
_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
_ui->directoryPathEdit->setText(getDirectoryPath());
checkDirectoryPathAndUpdateTree(getDirectoryPath());
QObject::connect(_ui->browseButton, &QPushButton::pressed, this, &MyExampleDialog::directoryPathEntered);
QObject::connect(_ui->directoryPathEdit, &QLineEdit::textChanged, this, &MyExampleDialog::checkDirectoryPathAndUpdateTree);
}
MyExampleDialog::~MyExampleDialog()
{
delete _ui;
}
void MyExampleDialog::directoryPathEntered()
{
const QString currentPath = getDirectoryPath();
QString newPath = QFileDialog::getExistingDirectory(this, tr("Select the installation directory"), currentPath);
if(newPath.isEmpty())
return;
_ui->directoryPathEdit->setText(newPath);
// then write newPath to QSettings
}
QString MyExampleDialog::getDirectoryPath() const
{
// retrieve path from QSettings
}
void MyExampleDialog::checkDirectoryPathAndUpdateTree(const QString& pathCheck)
{
if(std::filesystem::exists(pathCheck.toStdString()+"/bin/config.xml"))
{
QStringList filters;
filters << "*.jpeg";
QFileSystemModel *model = new QFileSystemModel(this);
model->setRootPath(pathCheck+QString::fromUtf8("/Images"));
model->setReadOnly(true);
model->setFilter(QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot);
model->setNameFilters(filters);
_ui->imgTreeView->setModel(model);
_ui->imgTreeView->setRootIndex(model->setRootPath("/Images"));
_ui->imgTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
QObject::connect(_ui->imgTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MyExampleDialog::updateImgSelection);
QObject::connect(_ui->imgTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MyExampleDialog::validateSelection);
}
else
{
if(pathCheck.isEmpty()) { }
else
{
QMessageBox::critical(this, tr("Error"), tr("No config.xml file in installation /bin directory"));
}
_ui->imgTreeView->setModel(nullptr);
}
}
QStringList MyExampleDialog::updateImgSelection()
{
QItemSelectionModel *selModel = _ui->imgTreeView->selectionModel();
QModelIndexList selIndices = selModel->selectedIndexes();
QStringList imgSel;
QFileSystemModel *fsModel = static_cast<QFileSystemModel*>(_ui->imgTreeView->model());
foreach(QModelIndex index, selIndices)
{
// parse data to obtain file name
}
return imgSel;
}
void MyExampleDialog::validateSelection()
{
QStringList imgList = updateImgSelection();
if(! imgList.isEmpty())
{
_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
else { _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); }
}
void MyExampleDialog::accept()
{
// do stuff when OK is clicked
}

注意,在函数checkDirectoryPathAndUpdateTree中,我们使用new声明指向新 QFileSystemModel 对象的指针。此指针不能在此函数的范围内使用delete删除,因为我希望模型持久存在,以便updateImgSelection可以使用它。这似乎是QFileSystemModel对象的标准用法,但C++我们被教导永远不要new实例化对象,而不必随后使用delete来释放内存。我的问题是QFileSystemModel的这种使用是否会导致内存泄漏,如果是,如何避免它?

欢迎来到C++和Qt的有趣世界。 您对将"新"与"删除"配对是正确的。 但是,Qt的引擎会为您进行大量的对象管理。

简短的回答:这不会导致内存泄漏

较长的简短答案:这不会导致内存泄漏。 你正在创建一个对象,并告诉Qt这个对象的父对象是"this"。 Qt现在让你的对象处于父子关系中,"this"是父对象,你的新对象是子对象。 删除父项后,子项将随之删除。

但是,请帮自己一个忙,花时间了解Qt如何处理对象以及何时由您来处理实例。 如果你不这样做,你可能会发现自己有非常令人沮丧的内存泄漏,看似随机的崩溃,或者"丢失"你认为应该存在的对象。

祝你好运,坚持下去。