问题描述
如上图所示,我要实现在 文件搜索
界面点击左上角的 Home
键会到首页,实现起来似乎也很简单代码如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void MainWindow::on_actionHome_triggered() { QWidget *currentCentralWidget = takeCentralWidget(); if (currentCentralWidget) { delete currentCentralWidget; } setCentralWidget(ui->centralWidget);
ui->fileView->setModel(fileModel); ui->fileView->setRootIndex(fileModel->index(QDir::currentPath())); ui->fileView->setViewMode(QListView::IconMode); ui->fileView->setIconSize(QSize(64, 64));
connect(ui->tagListWidget, &QListWidget::itemClicked, this, &MainWindow::onTagSelected); connect(ui->fileView, &QListView::clicked, this, &MainWindow::onFileClicked);
populateTags(); }
|
然而……
问题分析与探索
很显然,是一个内存访问的问题,ui->centralwidget
在被访问时已经无效,这意味着它可能在某处被删除或未正确初始化。那就检查一下,是什么原因导致ui->centralwidget
被错误的删除吧。
初步猜测,是文件搜索页面在进行析构时释放UI导致的,
1 2 3 4 5
| FileSearch::~FileSearch() { threadPool->waitForDone(); delete ui; }
|
我尝试把 delete ui;
注释掉,然而问题并没有得到解决,反而导致了,文件搜索界面的 UI 组件没有得到释放,错误地显示在界面中。
问题解决
现在已经锁定了问题的根源,尝试了上述方法也行不通,那么就要找到一种很为合适的解决方案,为了确保在切换中央控件时不会重复删除,我在MainWindow
类中添加了一个新的成员变量homeWidget
,并在构造函数中初始化该控件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), fileModel(new QFileSystemModel(this)), fileTagSystem("tags.csv", "users.csv"), homeWidget(nullptr) {
ui->setupUi(this);
homeWidget = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(homeWidget); layout->addWidget(ui->splitter);
setCentralWidget(homeWidget);
}
|
接着,修改了on_actionHome_triggered
方法,确保返回主界面并清空文件视图,以保持初始状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void MainWindow::on_actionHome_triggered() { qDebug() << "进入 on_actionHome_triggered";
if (!homeWidget) { qDebug() << "homeWidget 指针为空!"; return; }
qDebug() << "设置中央控件为 homeWidget。"; setCentralWidget(homeWidget);
initializeView();
connect(ui->tagListWidget, &QListWidget::itemClicked, this, &MainWindow::onTagSelected); connect(ui->fileView, &QListView::clicked, this, &MainWindow::onFileClicked);
populateTags(); }
|
总结
一句话总结一下:解决这个问题的关键在于正确管理中央控件的生命周期。