一、信号和槽
Qt中使用信号和槽机制来完成对象之间的协同操作,信号和槽都是函数,例如,单击窗口上的一个按钮时,想要弹出一个对话框,那么可以将这个按钮的单击信号和自定义的槽关联起来,在这个槽中创建一个对话框并且显示它。这样单击信号时就会发射信号,进而执行槽来显示一个对话框。
例子:
1、信号和槽的手动关联
(1)在Qt Creator上新建一个项目,选择 文件——新建文件或项目——Application——Qt Widgets Application,项目名为mydialog1,基类选择QWidget,类名为MyWidget。双击mywiget.ui文件,在设计模式中往界面添加一个Label和一个Push Button,在属性栏中将Push Button的objectName改为showChildButton,然后更改Label的显示文本为“我是主界面!”,更改按钮的显示文本为“显示子窗口”。
(2)双击mywidget.h文件,在MyWidget类声明的最后添加槽的声明:
public slots: void showChildDialog();这里自定义了一个槽,槽一般使用slots关键字进行修饰(Qt4中必须使用,Qt5中使用新的connect语法时可以不用,为了与一般函数进行区分,建议使用),这里使用的public slots,表明这个槽可以在类外被调用。
(3)到源文件中编写这个槽的实现代码
Qt Creator提供了一个快速添加定义的方法:在showChildDialog函数上右击,在弹出的级联菜单中选择Refactor菜单项,然后点击“在mywidget.cpp添加定义”,确认后,编辑器会转到mywidget.cpp文件中,并且已自动创建了showChildDialog()槽的定义。这种方法也用于先在源文件中添加,然后自动在头文件中添加声明。
在mywidget.cpp文件中将showChildDialog()槽的实现更改如下:
void MyWidget::showChildDialog() { QDialog *dialog = new QDialog(this); dialog->show(); }
(4) 更改MyWidget类的构造函数
MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget) { ui->setupUi(this); connect(ui->showChildButton,&QPushButton::clicked,this,&MyWidget::showChildDialog) }
这里使用了connect()函数将按钮的单击信号clicked()与新建的槽进行关联,这是信号和槽的手动关联方式。clicked()信号在QPushButton类中定义,而connect()是在QObject类中定义的函数,以为MyWidget类继承自QObject,所以可以直接使用。
connect函数的4个参数为:发射信号的对象、发射的信号、接受信号的对象、要执行的槽
程序运行结果:
2、信号和槽的自动关联
自动关联就是将关联函数整合到槽命名中,前面定义的槽可以重命名为on_showChildButton_clicked()就是由字符on、发射信号的部件对象名和信号组成。
(1)打开mywidget.cpp文件,删除上文定义的connect()函数,然后更改showChildDialog()槽的名字。Qt Creator提供了一个快速更改名字的方法:在原函数上右击,在弹出的级联菜单中选择Refactor,然后选择Renname Symbol Under Cursor,更改为on_showChildButton_clicked(),这时源文件和头文件中相应的函数都进行了更改,这就是信号和槽的自动关联。
void MyWidget::on_showChildButton_clicked() { QDialog *dialog = new QDialog(this); dialog->show(); }运行程序结果和上述相同。
在编写程序时一般使用第一种connect手动关联方式。
二、自定义对话框
基于上面的项目基础上进行自定义对话框的设计。
1、添加自定义对话框
项目——右键添加新文件——Qt——Qt设计师界面类,界面模板选择Dialog without Buttons,类名改为MyDialog,然后在设计模式想窗口添加2个Push Button,分别更改为“进入主界面”和“退出程序”。
2、设计信号和槽
下面使用两种方法进行信号和槽关联:
(1)使用设计器实现“退出程序”按钮信号和槽的关联(第一种方法)
进入设计界面,单击设计器上方的Edit Signals/Slots图标(或者按下F4),进入部件信号和槽的编辑模式。在“退出程序”按钮上单击鼠标左键,按住拖动至窗口界面上,松开左键,在弹出的配置链接对话框中,选择“显示从QWidget继承的信号和槽”,在左边的QPushButton栏中选择信号clicked(),右边QDialog栏中选择对应的槽close(),完成单击OK。
这时“退出程序”按钮的单击信号就和对话框中的关闭操作槽进行了关联。取消直接在界面上右键删除。关联好后,按下F3回到部件编辑模式。
(2)设置“进入主界面”按钮的信号和槽的关联(第二种方法:在设计器中直接进入相关信号的槽)
在“进入主界面”按钮上单击右键,在弹出的级联菜单中选择“转到槽”,然后在弹出的对话框中选择clicked()信号,单击OK,这时便会进入代码编辑模式,并且定位到自动生成的on_pushButton_clicked()槽中。在设计器中添加的部件要使用信号和槽,一般会使用此种方法。
在槽的函数定义下添加代码(mydialog.cpp文件):
void MyDialog::on_pushButton_clicked() { accept(); }accept()函数是QDialog类中的一个槽,对于使用exec()函数实现模态对话框,执行这个槽会隐藏这个模态对话框,并返回QDialog::Accepted值,这个值被用来判断哪个按钮被按下了。
3、在主界面中使用自定义的对话框
(1)更改main.cpp
#include "mywidget.h" #include <QApplication> #include"mydialog.h" //要把头文件添加进来,因为使用了MyDialog类 int main(int argc, char *argv[]) { QApplication a(argc, argv); MyWidget w; MyDialog dialog; //新建MyDialog类对象 if(dialog.exec() == QDialog::Accepted) //判断dialog的exec()的返回值,如果按下了“进入主界面”,则返回值是QDialog::Accepted,则往下执行显示 { w.show(); //如果是按下了"进入主界面"按钮,则显示主界面 return a.exec(); //程序正常运行 } else return 0; //否则,退出程序 }上述已实现从登录对话框到主界面,再从主界面显示一个对话窗口的应用。
(2)实现从主界面重新进入登录界面的功能
双击mywidget.ui文件,在设计模式中向界面添加两个Push Button,显示文本分别为“重新登陆”和“退出”,然后使用上述信号和槽的关联方法,将“退出”按钮的clicked()信号和MyWidget界面的close()槽关联;再转到“重新登陆”按钮的clicked()信号和槽,更改mywidget.cpp文件如下:
#include "mywidget.h" #include "ui_mywidget.h" #include"mydialog.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MyWidget) { ui->setupUi(this); } MyWidget::~MyWidget() { delete ui; } void MyWidget::on_showChildButton_clicked() { QDialog *dialog = new QDialog(this); dialog->show(); } void MyWidget::on_pushButton_clicked() { close(); //先关闭主界面,其实它是隐藏起来了,并没有真正的退出, MyDialog dlg; //用到MyDialog,故前面要加#include"mydialog.h",新建MyDialog类对象为dlg if(dlg.exec() == QDialog::Accepted) //此时是在“进入主窗口”和“退出程序”的界面, show(); //如何再次检测到“进入主界面”按下按钮的信号,则再次显示主界面 } //否则,若是其他信号,则程序将退出
close()槽的说明:
它不一定使程序退出,只有当只剩下最后一个主界面(就是没有父窗口的界面),这时调用close()槽,程序才会退出;而其他情况下,界面只是隐藏起来,并没有销毁。
程序运行结果:
单击“进入主界面”按钮:
单击“重新登陆”按钮:返回到登陆界面