我试图重写一个简单的“查找对话框”示例,而不使用指针作为类成员。我不知道为什么这段代码会导致此示例崩溃
//finddialog.h
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include<QtWidgets>
//#include <QDialog>
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = 0);
~FindDialog();
signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);
private slots:
void findClicked();
void enablefindButton(const QString &text);
private:
QLabel label{tr("Find &what:")};
QLineEdit lineEdit;
QCheckBox caseCheckBox{tr("Match &case")};
QCheckBox backwardCheckBox{tr("Search &bacward")};
QPushButton findButton{tr("&Find")};
QPushButton closeButton{tr("&Close")};
};
#endif // FINDDIALOG_H
这是实现
//finddialog.cpp
#include <QtWidgets>
#include "finddialog.h"
FindDialog::FindDialog(QWidget *parent)
: QDialog(parent)
{
label.setBuddy(&lineEdit);
findButton.setDefault(true);
findButton.setEnabled(false);
connect(&lineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enablefindButton(const QString &)));
connect(&findButton, SIGNAL(clicked()),
this, SLOT(findClicked()));
connect(&closeButton, SIGNAL(clicked()),
this, SLOT(close()));
QHBoxLayout topLeftLayout;
topLeftLayout.addWidget(&label);
topLeftLayout.addWidget(&lineEdit);
QVBoxLayout leftLayout;
leftLayout.addLayout(&topLeftLayout);
leftLayout.addWidget(&caseCheckBox);
leftLayout.addWidget(&backwardCheckBox);
QVBoxLayout rightLayout;
rightLayout.addWidget(&findButton);
rightLayout.addWidget(&closeButton);
rightLayout.addStretch();
QHBoxLayout mainLayout{this};
mainLayout.addLayout(&leftLayout);
mainLayout.addLayout(&rightLayout);
setLayout(&mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
FindDialog::~FindDialog()
{
}
void FindDialog::findClicked()
{
QString text = lineEdit.text();
Qt::CaseSensitivity cs = caseCheckBox.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if (backwardCheckBox.isChecked())
emit findPrevious(text,cs);
else
emit findNext(text,cs);
}
void FindDialog::enablefindButton(const QString &text)
{
findButton.setEnabled(!text.isEmpty());
}
主要就是这样
//main.cpp
#include <QApplication>
#include "finddialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FindDialog w;
w.show();
return a.exec();
}
我发现问题出在方法'addLyout'上,即注释所有对该方法的调用,应用程序不会崩溃。从文档中,该方法需要一个指向QLayout的指针作为输入,因此我已经传递了每个布局的地址,但是缺少一些东西。您能帮我弄清楚发生了什么吗?
答案 0 :(得分:1)
您的布局实例是堆栈变量,因此在构造函数返回后它们会被销毁。现在其他对象具有指向不再存在的实例的指针。这通常意味着当机。
将您的布局实例设为FindDialog
的私有成员,以防止这种情况发生。
请注意,在堆栈上创建QObject实例时,需要注意声明顺序。当QObject被销毁时,它将删除其所有子对象,除非它们已被销毁。这意味着您需要确保小部件在布局之前被销毁。 (这对于所有具有父/子关系的QObjects都是这样,而不仅仅是布局。)如果您不注意这一点,则父级将尝试删除堆栈中的子级(显然不允许这样做)。 / p>
类成员的销毁顺序与构造顺序相反。因此,宣布最后一名成员首先被销毁。对于QLayout子类,需要在其子窗口小部件之后 销毁它们。因此,您需要先声明它们:
private:
QHBoxLayout topLeftLayout;
QVBoxLayout leftLayout;
QVBoxLayout rightLayout;
QHBoxLayout mainLayout{this};
QLabel label{tr("Find &what:")};
QLineEdit lineEdit;
QCheckBox caseCheckBox{tr("Match &case")};
QCheckBox backwardCheckBox{tr("Search &bacward")};
QPushButton findButton{tr("&Find")};
QPushButton closeButton{tr("&Close")};
这是为什么您看到的大多数Qt代码都在堆上(使用new
分配QObject的原因之一。将它们放到堆上时,您不必担心此问题。显然,当拥有永远不会被删除的无父母对象时,您可能会遇到内存泄漏。所以选择你的毒药。