Qt:SIGNAL和SLOT在自定义QDialog窗口中不起作用

时间:2018-10-26 09:21:52

标签: c++ qt qt-designer qdialog

我有一个应用程序,我想在其中提示一个对话框,以进一步(高级)编辑应用程序内容。它必须是模式窗口,因此这就是不能成为QMainWindow的原因。我似乎无法在connect()窗口中使QDialog宏正常工作。

以前,我通过在对话框类中使用QDialog的响应和getter函数来解决此问题:

简单查询的屏幕截图

Dialog_CreateNew mDialog(this);
mDialog.setModal(true);
if (mDialog.exec() == QDialog::Accepted)
{
    QString username, password;
    mDialog.getData(&username, &password);
}

我使用了QDialog库accept()reject()的内置SLOT:

connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
connect(_createNew, SIGNAL(clicked()), this, SLOT(accept()));

但是现在当我必须在对话框窗口中创建自己的插槽时,请idk如何使其工作。这将是一个复杂的窗口,只是accept()和reject()不会这样做。

另一件事:当我在对话框类中添加Q_OBJECT宏时,出现错误:

  

错误:未定义对Dialog_CreateNew的vtable的引用

这些内置插槽accept()reject()在没有Q_OBJECT的情况下工作。

我已经在Qt Designer中看到了这项工作,因此是可能的。我不想使用设计器,所有事情都应该在编码中完成。

那是我的研究,也是我尝试的事情。

我的问题是:如何在模态子对话框窗口中使信号插槽机制工作?

“ dialog_createNew.h”:

#ifndef DIALOG_CREATENEW_H
#define DIALOG_CREATENEW_H

#include <QtCore>
#include <QDialog>
#include <QIcon>
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QGridLayout>
#include <QPushButton>
#include <QMessageBox>
#include <QStatusBar>

class Dialog_CreateNew : public QDialog

{
    Q_OBJECT
public:
    Dialog_CreateNew(QWidget* parent);
    void getData(QString* username, QString* password);
    void setErrorTip(QString errorTip);
    virtual ~Dialog_CreateNew();
private:
    QWidget* _parent;
    QLabel* _lInstruction;
    QLabel* _lUsername;
    QLabel* _lPassword;
    QLineEdit* _edUsername;
    QLineEdit* _edPassword;
    QPushButton* _createNew;
    QPushButton* _cancel;

    QLabel* _lErrorTip;
    QString* _errorTip;

    QGridLayout* _layout;

    void createConnects();

private slots:
    void onTextChanged_connect(QString);

};

#endif // DIALOG_CREATENEW_H

“ dialog_createNew.cpp”:

#include "dialog_createnew.h"

Dialog_CreateNew::Dialog_CreateNew(QWidget* parent)
{
    _parent = parent;
    this->setWindowTitle("Create New Bot");
    this->setWindowIcon(QIcon(":/icons/createNew.svg"));
    int nHeight = 150;
    int nWidth = 360;
    this->setGeometry(parent->x() + parent->width()/2 - nWidth/2,
                    parent->y() + parent->height()/2 - nHeight/2,
                    nWidth, nHeight);
    this->setFixedSize(QSize(nWidth, nHeight));

    _lInstruction = new QLabel(this);
    _lInstruction->setText("Enter Your Instagram credentials:");

    _lUsername = new QLabel(this);
    _lUsername->setText("Username:");

    _lPassword = new QLabel(this);
    _lPassword->setText("Password:");

    _edUsername = new QLineEdit(this);
    _edUsername->setPlaceholderText("classybalkan");

    _edPassword = new QLineEdit(this);
    _edPassword->setEchoMode(QLineEdit::Password);
    _edPassword->setPlaceholderText("•••••••••••");

    _createNew = new QPushButton(this);
    _createNew->setText("Create New Bot");

    _cancel = new QPushButton(this);
    _cancel->setText("Cancel");

    _errorTip = new QString("");
    _lErrorTip = new QLabel(this);


    _layout = new QGridLayout(this);
    _layout->addWidget(_lInstruction, 0, 0, 1, 2);
    _layout->addWidget(_lUsername, 1, 0);
    _layout->addWidget(_edUsername, 1, 1);
    _layout->addWidget(_lPassword, 2, 0);
    _layout->addWidget(_edPassword, 2, 1);
    _layout->addWidget(_lErrorTip, 3, 1);
    _layout->addWidget(_cancel, 4, 0);
    _layout->addWidget(_createNew, 4, 1);

    this->setLayout(_layout);

    createConnects();
}

void Dialog_CreateNew::createConnects()
{
    connect(_cancel,
            SIGNAL(clicked()),
            this,
            SLOT(reject()));
    connect(_edPassword,
             &QLineEdit::textChanged,
             this,
             &Dialog_CreateNew::onTextChanged_connect);
}

void Dialog_CreateNew::getData(QString* username, QString* password)
{
    *username = _edUsername->text();
    *password = _edPassword->text();
}

void Dialog_CreateNew::setErrorTip(QString errorTip)
{
    *_errorTip = errorTip;
    _lErrorTip->setText("<center><font color=""red"">"
                       + *_errorTip +
                       "</font><center>");
}

void Dialog_CreateNew::onTextChanged_connect()
{
    QString text = _edPassword->text();
    if (text == "")
    {
        disconnect(_createNew,
             &QPushButton::clicked,
             this,
             &QDialog::accept);
        _lErrorTip->setText("Invalid Password");
    }
    else
    {
        connect(_createNew,
             &QPushButton::clicked,
             this,
             &QDialog::accept);
    }
}

Dialog_CreateNew::~Dialog_CreateNew()
{

}

解决方案: 使用新的函数绑定更改旧的SIGNAL / SLOT表示法:

connect(_edPassword, &QLineEdit::textChanged, this, &Dialog_CreateNew::onTextChanged_connect);

这使我可以使用自己的插槽并进行修复。

1 个答案:

答案 0 :(得分:1)

要解决此问题,您应该做三件事:

  1. 将工作拆分为标头(.h文件)和源文件(.cpp文件)
  2. 将对话框的析构函数定义为虚拟的,例如:

    virtual ~MyDialog()
    {
    }
    
  3. 再次运行qmake

其中一个或多个将为您解决

PS:请哦,请...停止使用过时的SIGNAL()SLOT(),并开始使用使用函数绑定的新格式,例如:

connect(_cancel, &QPushButton::clicked, this, &QDialog::reject);

它更快,更高效,不使用字符串,并且一旦编译即可工作。与旧的格式可能会在运行时失败。