03Qt信号与槽(2)
1. 元对象工具
元对象编译器 MOC(meta object compiler)对 C++ 文件中的类声明进行分析并产生用于初始化元对象的 C++ 代码,元对象包含全部信号和槽的名字及指向这些函数的指针。
MOC 读 C++ 源文件,如果发现有 Q_OBJECT 宏声明的类,它就会生成另外一个 C++ 源文件,这个新生成的文件中包含有该类的元对象代码。例如,假设我们有一个头文件 mysignal.h,在这个文件中包含有信号或槽的声明,那么在编译之前 MOC 工具就会根据该文件自动生成一个名为 mysignal.moc.h 的 C++ 源文件并将其提交给编译器;类似地,对应于 mysignal.cpp 文件 moc 工具将自动生成一个名外 mysignal.moc.cpp 的文件提交给编译器。
元对象代码是 signal/slot 机制所必须的。用 MOC 产生的 C++ 源文件必须和类实现一起进行编译和链接,或用 #inldue 语句将其包含到类的源文件中。MOC 并不扩展 #include 或 #define 宏定义,他只是简单的跳过所遇见的所有预处理指令。
2. 程序示例
这里给出了一个简单的示例程序,程序中定义了三个信号、三个槽函数,然后将信号和槽进行关联,每个槽函数值是简单的弹出一个对话框窗口。
信号和槽函数的声明一般位于头文件中,同时在类声明单的开始位置必须加上 Q_OBJECT 语句,这条语句是不可或缺的,它将告诉编译器在编译之前必须先应用 MOC 工具进行扩展。关键字 signals 指出随后开始信号的声明,这里 signals 用的是复数形式而非单数,signals 没有 public、private、protected 等属性,这点不同于 slots。另外,signal、slots 关键字是 Qt 自己定义的,不是 C++ 中的关键字。
信号的声明类似于函数的声明而非变量的声明,左边要有类型,右边要有括号,如果要向槽中传递参数的话,在括号中指定每个参数的类型,当然,形式参数的个数能多于一个。
关键字 slots 指出随后开始槽的声明,这里 slots 用的也是复数形式。
槽的声明和普通寒时候的声明相同,能携带零或多个形式参数。既然信号的声明类似于普通 C++ 函数的声明,那么,信号也可采用 C++ 中重载函数的形式进行声明,即同名但参数不同。例如,第一次定义的 void mySignal 没有带参数,而第二次定义的却带有参数,从这里我们能看到 Qt 的信号机制是非常灵活的。
信号和槽之间的联系必须事先用 connect 函数进行指定。如果要断开二者之间的联系,使用函数 disconnect。
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
signals:
//信号声明区
void mySignal();
void mySignal(int x);
void mySignalPraam(int x, int y);
public slots:
//槽声明区
void mySlot();
void mySlot(int x);
void mySlotParam(int x, int y);
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(this, SIGNAL(mySignal()), SLOT(mySlot()));
connect(this, SIGNAL(mySignal(int)), SLOT(mySlot(int)));
connect(this, SIGNAL(mySignalPraam(int,int)), SLOT(mySlotParam(int,int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::mySlot()
{
QMessageBox::about(this, "MainWindow","This is a signal/slot sample without parameter!");
}
void MainWindow::mySlot(int x)
{
QMessageBox::about(this, "MainWindow", "This is a signal/slot sample with one parameter!");
}
void MainWindow::mySlotParam(int x, int y)
{
char s[256];
sprintf(s, "x:%d y:%d", x, y);
QMessageBox::about(this, "MainWindow", s);
}
void MainWindow::on_pushButton_clicked()
{
//发射信号
emit mySignal();
emit mySignal(500);
emit mySignalPraam(100, 200);
}
3. 应注意的问题
信号和槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中才能做到有的放矢,避免产生一些错误。
(1)信号和槽的效率是非常高的,不过同真正的回调函数比起来,由于增加了灵活性,因此在速度上海市有所损失,当然这种损失相对来说是比较小的,通过在一台 i586-133 的集市上测试是 10 微秒(运行Linux),可见这种机制所提供的简洁性、灵活性还是值得的。但如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。
(2)信号和槽机制和普通函数的调用相同,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接受到的同样信号。例如,在前面给出的例子中如果在 mySlot 槽函数中加上语句 emit Sginal 即可形成死循环。
(3)如果一个信号和多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序是随机的。
(4)宏定义不能用在 signal 和 slot 的参数中。既然 MOC 工具不扩展 #define,因此, 在 signals 和 slots 中携带参数的宏就不能正确地工作,如果不带参数则是可以的。
(5)构造函数不能用在 signals 或 slots 声明区域内。
(6)函数指针不能作为信号或槽的参数。
class someClass:public QObject
{
Q_OBJECT
...
public slots:
void apply(void(*applyFunction)(QList*, void*), char*);
}
//但是,可以通过采用函数指针的 typedef 来绕过这个限制
typedef void(*ApplyFunctionType)(QList*, void*);
class someClass:public QObject
{
Q_OBJECT
...
public slots:
void apply(AppfunctionType, char*);
}
(7)信号和槽不能有缺省值。
既然 signal/slot 绑定时发生在运行时的,那么,从概念上讲使用缺省参数是困难的。
(8)信号和槽也不能携带模板类参数。
如果将信号、槽声明为模板类参数的话,即时 MOC 工具不报告错误,也不可能得到预期的结果。
(9)嵌套的类不能位于信号或槽区域内,也不能有信号或槽。
(10)友元声明不能位于信号或才声明区内。相反,它们应该在普通 C++ 的 private、protected或public 区内进行声明。
03Qt信号与槽(2)的更多相关文章
- qt5中信号和槽的新语法
qt5中的连接 有下列几种方式可以连接到信号上 旧语法 qt5将继续支持旧的语法去连接,在QObject对象上定义信号和槽函数,及任何继承QObjec的对象(包含QWidget). connect(s ...
- Qt信号与槽自动关联机制
参考链接1:http://blog.csdn.net/skyhawk452/article/details/6121407 参考链接2:http://blog.csdn.net/memory_exce ...
- pyqt信号和槽应用举例
第一篇手写随笔. 项目的部分代码: 在子线程中改变主窗体的标签. class MyForm(QDialog): def __init__(self, parent=None): self.config ...
- 在Qt Creator 和在 vs2012 里添加信号和槽
原文地址:http://www.cnblogs.com/li-peng/p/3644812.html 作者:李鹏 出处:http://www.cnblogs.com/li-peng/ 本文版权归作者和 ...
- QT点击"X"按钮,调用closeEvent()函数来实现调用特定事件(附:粗略介绍QT的信号与槽的使用方法)
背景: QT在用户关闭窗口(直接点击"X"键)时,程序一般都需要做一些善后的事情,就我现在的程序来说,既关闭USB.如何实现? 正文: 首先,在对应窗体的".h" ...
- QT 信号与槽connect
QT 信号与槽connect QT 信号与槽connect connect函数调用几个限制 connect函数代码 QT中信号与槽的连接使用的connect函数是一个静态函数,在类QObject中定义 ...
- Qt之自定义信号和槽函数
自定义信号和槽函数: 1.类的声明和实现分别放在.h和.cpp文件中: 2.类声明包含Q_OBJECT宏: 3.信号只要声明不要设计其的实现函数 4.发射信号用emit关键字 5.自定义槽的实现与普通 ...
- Qt信号与槽应用实例一
..... connect(m_pGlobelWidget,signal(globeControlClick(object,object)),this,slot(globeControlClick(o ...
- qt中信号与槽机制
一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不 ...
随机推荐
- [WebShow系列] 倒计时展示相关问题
WebShow内置了倒计时功能. 后台参数维护: 倒计时参数说明: 倒计时基准时间设置(秒数):假设设置为90,也就是从1分30秒开始倒计时,同时有开始提示音. 倒计时提示1剩余秒数:假设设置为30, ...
- CSS样式之操作属性一
********css之操作属性******** 一.文本 1.文本颜色:color 颜色属性被用来设置文字的颜色 颜色是通过CSS最经常的指定: 十六进制值 - 如: #FF0000 一个RGB值 ...
- [TCP/IP]ARP与RARP的总结
一. 总述 简单的说,ARP协议就是将IP地址转换为MAC物理地址:而RARP,就是ARP的逆向,也就是将MAC物理地址转换为IP地址.看起来这两个协议是完全对称的,但发明这两个协议的初衷基本上没有什 ...
- [Android]四大组件的运行状态
Activity的主要作用是展示一个界面并和用户交互,它扮演的是一种前台界面的角色. Service是一种计算型组件,用于在后台执行一系列计算任务.Service有两种状态:启动状态和绑定状态.启动状 ...
- [LOJ 2082] 「JSOI2016」炸弹攻击 2
[LOJ 2082] 「JSOI2016」炸弹攻击 2 链接 链接 题解 枚举发射源,将发射源当做原点,对敌人和激光塔极角排序. 由于敌人纵坐标均为正,而其它点均为负,因此每两个角度差在 \(\pi\ ...
- Spark Mllib里决策树二元分类使用.areaUnderROC方法计算出以AUC来评估模型的准确率和决策树多元分类使用.precision方法以precision来评估模型的准确率(图文详解)
不多说,直接上干货! Spark Mllib里决策树二元分类使用.areaUnderROC方法计算出以AUC来评估模型的准确率 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的 ...
- js基础拖拽效果
function drag(ele) { const config = { mark: 0, x: 0, y: 0, left: ele.offsetLeft, top: ele.offsetTop, ...
- JsonModel&AFNetWorking
// HttpManager.h // JsonModel&AFNetWorking // // Created by qianfeng on 15/7/21. // Copyright (c ...
- JVM类加载之创建对象的过程
JVM对象的创建 new一个对象到底发生了什么? 1.VM遇到new关键字:首先检查是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否被加载,验证,准备,解析,初始化过,如果没有, ...
- tcp的三次连接握手和四次释放握手
http://blog.csdn.net/whuslei/article/details/6667471/ 这篇博客讲的很清楚. 下面我简单说明一下:三次连接握手,首先client发送请求报文,然后服 ...