首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >QT: addLayout导致崩溃

QT: addLayout导致崩溃
EN

Stack Overflow用户
提问于 2019-05-22 03:59:56
回答 1查看 161关注 0票数 0

我试图重写一个简单的“查找对话框”示例,而不使用指针作为类成员。我搞不懂为什么这段代码会导致这个例子崩溃

代码语言:javascript
复制
//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

这就是实现

代码语言:javascript
复制
//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就是这样的

代码语言:javascript
复制
//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的指针作为输入,所以我已经传递了每个布局的地址,但我遗漏了一些东西。你能帮我弄清楚是怎么回事吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-22 04:18:48

您的布局实例是堆栈变量,因此它们在构造函数返回后被销毁。其他对象现在具有指向不再存在的实例的指针。这通常意味着崩溃。

让你的布局实例成为FindDialog的私有成员,以防止这种情况发生。

请注意,在堆栈上创建QObject实例时,需要注意声明顺序。当QObject被销毁时,它将删除其所有子对象,除非它们已经被销毁。这意味着你需要确保你的小部件在它们的布局被销毁之前被销毁。(这适用于所有具有父/子关系的QObjects,而不仅仅是布局。)如果你不注意这一点,父母会尝试删除堆栈中的孩子(显然,这是不允许的)。

类成员的销毁顺序与构造顺序相反。所以最后声明的成员首先被销毁。在QLayout子类的情况下,它们需要在它们的子部件之后被销毁。所以你需要先声明它们:

代码语言:javascript
复制
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代码都是在堆上分配QObjects (使用new)的原因之一。在将它们放到堆上时,您不必担心这个问题。显然,当您拥有从未被删除的无父对象时,您可能会遇到内存泄漏。所以选择你的毒药吧。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56245573

复制
相关文章

相似问题

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