Qt:SIGNAL 和 SLOT 在自定义 QDialog 中不起作用 window
Qt: SIGNAL and SLOT don't work in a custom QDialog window
我有一个应用程序,我想在其中提示一个对话框 window 以进一步(高级)编辑应用程序内容。它必须是模态window,所以它不能是QMainWindow
。我似乎无法让 connect()
宏在 QDialog
window.
中工作
以前,我通过在对话框 class:
中使用 QDialog
和 getter 函数的响应来解决这个问题
简单查询的截图
Dialog_CreateNew mDialog(this);
mDialog.setModal(true);
if (mDialog.exec() == QDialog::Accepted)
{
QString username, password;
mDialog.getData(&username, &password);
}
我使用了 QDialog 库的内置 SLOT accept()
和 reject()
:
connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
connect(_createNew, SIGNAL(clicked()), this, SLOT(accept()));
但是现在当我必须在对话框中创建自己的插槽时 window,我不知道如何让它工作。这将是一个复杂的 window,仅接受 () 和拒绝 () 不会这样做。
还有一件事:当我在对话框 class 中添加 Q_OBJECT
宏时,出现错误:
error: undefined reference to `vtable for Dialog_CreateNew'
这些内置插槽 accept()
和 reject()
在没有 Q_OBJECT
的情况下工作。
我在 Qt Designer 中看到过这项工作,因此它是可能的。我不想使用设计器,一切都应该在编码中完成。
那是我的研究和我尝试过的东西。
我的问题是:如何使信号槽机制在模态子对话框中工作window?
"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);
这让我可以使用自己的插槽,并进行了修复。
解决此问题的三件事:
- 将您的工作拆分为 header(.h 文件)和源代码(.cpp 文件)
将对话框的析构函数定义为虚拟的,例如:
virtual ~MyDialog()
{
}
运行 再次 qmake
其中一项或多项将为您解决问题
PS:请,哦,请...停止使用过时的 SIGNAL()
和 SLOT()
,并开始使用使用函数绑定的新格式,例如:
connect(_cancel, &QPushButton::clicked, this, &QDialog::reject);
它更快、更高效,不使用字符串,而且一旦编译就可以工作。与可能在运行时失败的旧格式不同。
我有一个应用程序,我想在其中提示一个对话框 window 以进一步(高级)编辑应用程序内容。它必须是模态window,所以它不能是QMainWindow
。我似乎无法让 connect()
宏在 QDialog
window.
以前,我通过在对话框 class:
中使用QDialog
和 getter 函数的响应来解决这个问题
简单查询的截图
Dialog_CreateNew mDialog(this);
mDialog.setModal(true);
if (mDialog.exec() == QDialog::Accepted)
{
QString username, password;
mDialog.getData(&username, &password);
}
我使用了 QDialog 库的内置 SLOT accept()
和 reject()
:
connect(_cancel, SIGNAL(clicked()), this, SLOT(reject()));
connect(_createNew, SIGNAL(clicked()), this, SLOT(accept()));
但是现在当我必须在对话框中创建自己的插槽时 window,我不知道如何让它工作。这将是一个复杂的 window,仅接受 () 和拒绝 () 不会这样做。
还有一件事:当我在对话框 class 中添加 Q_OBJECT
宏时,出现错误:
error: undefined reference to `vtable for Dialog_CreateNew'
这些内置插槽 accept()
和 reject()
在没有 Q_OBJECT
的情况下工作。
我在 Qt Designer 中看到过这项工作,因此它是可能的。我不想使用设计器,一切都应该在编码中完成。
那是我的研究和我尝试过的东西。
我的问题是:如何使信号槽机制在模态子对话框中工作window?
"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);
这让我可以使用自己的插槽,并进行了修复。
解决此问题的三件事:
- 将您的工作拆分为 header(.h 文件)和源代码(.cpp 文件)
将对话框的析构函数定义为虚拟的,例如:
virtual ~MyDialog() { }
运行 再次 qmake
其中一项或多项将为您解决问题
PS:请,哦,请...停止使用过时的 SIGNAL()
和 SLOT()
,并开始使用使用函数绑定的新格式,例如:
connect(_cancel, &QPushButton::clicked, this, &QDialog::reject);
它更快、更高效,不使用字符串,而且一旦编译就可以工作。与可能在运行时失败的旧格式不同。