典型实例
在主界面中创建一个对话框,在这个对话框中可以输入姓名、编号,当单击"确定"按钮时,关闭对话框,然后将输入的编号通过信号发射出去,最后在主界面中接收该信号并且显示编号数值
项目建立完成后,向项目中添加新文件,模板选择Qt分类中的"Qt设计器界面类",界面模板选择Dialog without Buttons,类名设置为MyDialog。
在mydialog.h文件中添加代码来声明一个信号:
c
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog>
#include<string>
namespace Ui {
class MyDialog;
}
class MyDialog : public QDialog
{
Q_OBJECT
public:
explicit MyDialog(QWidget *parent = nullptr);
~MyDialog();
private:
Ui::MyDialog *ui;
signals:
void dlgReturn(std::string, int);//声明信号
};
#endif // MYDIALOG_H
声明一个信号要使用signals关键字,在signals前面不能用public、private或protected等关键字,因为信号默认是public函数,可以从任何地方进行发射,但是建议只在声明该信号的类及其子类中发射该信号。信号只用声明,不需要也不能对它进行定义实现。还要注意,信号没有返回值,只能是void类型的。因为只有QObject类及其子类派生的类才能使用信号和槽机制,这里的MyDialog类继承自QDialog类,QDialog类又继承自QWidget类,QWidget类是QObject类的子类,所以这里可以使用信号和槽。另外,使用信号和槽还必须在类定义的最开始处添加Q_OBJECT宏。
双击mydialog.ui文件进入设计模式,在界面中添加一个Spin Box部件和一个Push Button部件换位一个lineEdit,将pushButton的显示文本修改为"确定"。
SpinBox用于整数的显示与输入,一般显示为十进制,也可以显示二进制和十六进制的数,而且可以在显示框增加前缀和后缀
lineEdit 输入姓名使用
转到pushButton的单击信号clicked()对应的槽,更改如下。
c
void MyDialog::on_pushButton_clicked()
{
int index = ui->spinBox->value();
std::string name = ui->lineEdit->text().toStdString();
emit dlgReturn(name,index); //获取输入值
qDebug() << " index :" << index << " name :" << name;
}
击"确定"按钮便可以获取spinBox部件中的数值,然后使用自定义的信号将其作为参数发射出去。发射一个信号要使用emit关键字,例如这里发射了dlgReturn()信号。
connect()函数的最后一个参数type表明了关联的方式,由Qt::ConnectionType枚举类型指定,其默认值是Qt::AutoConnection,还有其他几个选择,在MyDialog类中使用emit发射信号之后,就会立即执行槽,只有等槽执行完以后,才会执行emit语句后面的代码。这里可以将这个参数改为Qt::QueuedConnection,这样在执行完emit语句后便会立即执行其后面的代码,而不管槽是否已经执行,可以通过"应用程序输出"窗口的信息查看效果。
然后到widget.h文件中添加自定义槽的声明:
c
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<string>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
private slots:
void showindex(const std::string& name, int index);
};
#endif // WIDGET_H
下面打开widget.ui文件,向界面上拖入一个Label部件,更改其文本为"用户信息:"。
然后进入widget.cpp文件中,添加头文件#include "mydialog.h",再在构造函数中添加如下代码。
c
#include "widget.h"
#include "ui_widget.h"
#include "mydialog.h"
#include <QString>
#include <QDebug>
#include <String>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
MyDialog *dlg = new MyDialog(this);
connect(dlg, SIGNAL(dlgReturn(const std::string&, int)),
this, SLOT(showindex(const std::string&, int)));
dlg->show();
}
Widget::~Widget()
{
delete ui;
}
void Widget::showindex(const std::string& name, int index)
{
// 将std::string转换为QString
QString qName = QString::fromStdString(name);
ui->label_2->setText(tr("%1").arg(qName));
ui->label_3->setText(tr("%1").arg(index));
qDebug() << "name: " << name ;
qDebug() << "index: " << index ;
}
这里创建了一个MyDialog实例dlg,并且使用Widget作为父部件。然后将MyDialog类的dlgReturn()信号与Widget类的showValue()槽进行关联。
升级一下
将dlg定义为类成员,实现的功能是点击后dlg会关闭
widget.cpp
c
#include "widget.h"
#include "ui_widget.h"
#include "mydialog.h"
#include <QString>
#include <QDebug>
#include <String>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
Widget::showdlg();
}
Widget::~Widget()
{
delete ui;
}
void Widget::showdlg()
{
dlg = new MyDialog(this);
connect(dlg, SIGNAL(dlgReturn(const std::string&, int)),
this, SLOT(showindex(const std::string&, int)));
dlg->show();
}
void Widget::showindex(const std::string& name, int index)
{
// 将std::string转换为QString
QString qName = QString::fromStdString(name);
ui->label_2->setText(tr("%1").arg(qName));
ui->label_3->setText(tr("%1").arg(index));
qDebug() << "name: " << name ;
qDebug() << "index: " << index ;
dlg->close();
}
widget.h
c
#ifndef WIDGET_H
#define WIDGET_H
#include "mydialog.h"
#include <QWidget>
#include<string>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void showdlg();
private:
Ui::Widget *ui;
MyDialog *dlg;
private slots:
void showindex(const std::string& name, int index);
};
#endif // WIDGET_H
总结
这里实现了自己定义类,自己声明信号,关联槽函数。
注意
●需要继承自QObject类或其子类。
●在类定义的最开始处私有部分添加Q_OBJECT宏。
●槽中参数的类型要和信号参数的类型相对应,且不能比信号的参数多。
●信号只用声明,没有定义,且返回值为void类型。
●connect()函数时,信号和槽的参数只能有类型,不能有变量名
●使用emit发射信号
connect()函数的使用方法
1、自动关联
2、常规使用
3、自己定义信号
2、lamda函数
cpp
QObject::connect(sender, &Sender::signal, [=](){
// 在这里编写需要执行的代码
});
参考
《零基础学Ot 6编程》