用qt的知道,qt有方便简单的信号槽机制,但需要专门的qt工具处理。 
如果想直接使信号槽就可以使用sigslot库,或者sigc++库,或者boost中的signals,这里介绍sigslot和sigc++库。

sigslot.h:只有一个头文件,使用简单方便。 
sigc++:包含文件多,但功能更强大。


sigslot库

官方地址

http://sigslot.sourceforge.net/

在vs2013中使用

  • 包含头文件
#include "sigslot.h"
  • 1
  • 1
  • 改动:
    //在sigslot.h的420,将:
typedef sender_set::const_iterator const_iterator;
//改为:
typedef typename sender_set::const_iterator const_iterator;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

基本使用:

  • signal0~signal8:信号类:作为类成员
    class mySg
{
sigc::signal0<> sg1; // 无参数
sigc::signal2<char*, double> sg2; // 2个参数
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • connection 
    槽函数:作为类成员,类需要继承has_slots<>,且槽函数的返回值必须是void类型
    class mySlot: public : has_slots<>
{
public:
void on_func1(){} // 无参数,与信号对应
void on_func2(char*, double)(){} // 2个参数
};
mySg sig;
mySlot slt;
sig.sg1.conncent(&slt,&mySlot::on_func1);
sig.sg2.conncent(&slt,&mySlot::on_func2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • disconnection 
    解除连接:可以使用disconnect()和disconnect_all()
    sig.sg1.disconnect(&slt);
sig.sg1.disconnect_all();
  • 1
  • 2
  • 1
  • 2
  • emiting 
    发送信号:可以直接使用()运算符,也可以调用signal的emit函数
    sig.sg1.emit();
sig.sg2("str",0.1);
  • 1
  • 2
  • 1
  • 2

实例:

#include <stdio.h>
#include <conio.h>
#include <cstdlib>
#include <iostream>
using namespace std; #include "sigslot.h"
using namespace sigslot; #define pause_wait() {std::cout << "\nPlease press any key to continue.\n";_getch();} // class
enum ObjState{Normal = 0, Hidden = 1};
class ObjectBase : public has_slots<>
{
public:
ObjectBase(){ px = 0; py = 0; state = Normal; }
ObjectBase(const int &x, const int &y):px(x), py(y){ state = Normal; }
~ObjectBase(){}; void onMoveBy(const int &x, const int &y){px += x; py += y;}
void onResize(const int &x, const int &y){px = x; py = y;}
void onSetState(ObjState s){this->state = s;}
void onPrintState()
{
if(state == Normal)
std::cout << "Normal" << std::endl;
else if(state == Hidden)
std::cout << "Hidden" << std::endl;
else
std::cout << "Error: error state value" << std::endl;
} const int& getX(){return px;}
const int& getY(){return py;}
const char* getState()
{
if(state == Normal)
return "Normal";
else if(state == Hidden)
return "Hidden";
else
return nullptr;
} private:
ObjState state;
int px;
int py;
}; class Control
{
public:
signal2<const int&, const int&> moveBy;
signal2<const int&, const int&> resize;
signal1<ObjState> setState;
signal0<> printState;;
}; int main(int argc, char* argv[])
{
ObjectBase obj(10,10);
Control ctrl; #if(1)
ctrl.moveBy.connect(&obj, &ObjectBase::onMoveBy);
ctrl.resize.connect(&obj, &ObjectBase::onResize);
ctrl.setState.connect(&obj, &ObjectBase::onSetState);
ctrl.printState.connect(&obj, &ObjectBase::onPrintState); //ctrl.moveBy.disconnect(&obj);
//ctrl.moveBy.disconnect_all(); // start pro loop
PRO_Start:
while(true)
{
system("cls");
cout << "Object Information" << endl;
cout << "\t Position_x: " << obj.getX() << endl;
cout << "\t Position_y: " << obj.getY() << endl;
cout << "\t State: " << obj.getState() << endl;
cout << "\n";
cout << "\t m: move object \n"
"\t r: resize object \n"
"\t s: set object state \n"
"\t p: print object state \n"
<< endl;
cout << "Input:"; char ch = getchar();
switch(ch)
{
case 'm': // move
ctrl.moveBy(10,10);
break;
case 'M':
ctrl.moveBy.emit(-20,-20);
break; case 'R':
case 'r': // resize
ctrl.resize.emit(0, 0);
break; case 'P':
case 'p': // printState
goto PRO_PrintState;
break; case 's': // setState
ctrl.setState(Normal);
break;
case 'S':
ctrl.setState.emit(Hidden);
break; case 'Q':
case 'q': // exit
goto PRO_Exit;
break;
default:
break;
}
} PRO_PrintState:
ctrl.printState.emit();
pause_wait();
goto PRO_Start; #endif
pause_wait(); PRO_Exit:
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139

sigc++库

官方地址

http://libsigc.sourceforge.net/

编译

可以在http://download.csdn.net/detail/yehuohan/9600368下载已经编好的库文件,2.8.0版 
注意1:在用高版本编译时,如2.8.0,可能会提示找不到msvc_recommended_pragmas.h,可以在vs的

属性 -> C/C -> 高级 -> 强制包含文件
  • 1
  • 1

去掉msvc_recommended_pragmas.h,或者添加一个msvc_recommended_pragmas.h文件,在http://download.csdn.net/detail/yehuohan/9600369的源代码时已经放入了该文件。 
注意2:在使用高版本(如2.9.7)编译时,若提示找不到slot.cc等文件,可以使用低版本中的放入相应位置即可。

在vs中使用

* 项目 -> VC++目录 -> 包含目录: 添加 sigc++所在的目录
* 添加下列代码:
        #include <sigc++/sigc++.h>
#ifdef _DEBUG
#pragma comment(lib,"sigcd.lib")
#else
#pragma comment(lib,"sigc.lib")
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

基本使用:

  • signal 
    信号类:可以作为其它类成员,也可直接定义
    //返回值: int,2个参数:char*, double,参数个数可以直接指定
sigc::signal<int, char*, double> sg1;
sigc::signal2<int, char*, double> sg2;
class mySg
{
sigc::signal2<int, char*, double> sg3;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • connection 
    连接槽函数,作为类成员时,要继承sigc::trackable; 
    ptr_fun, ptr_fun0~7 : 连接全局函数; 
    mem_fun, mem_fun0~7 : 连接类成员函数; 
    ptr_fun,mem_fun与signal之间只要参数类型对应就可连接, 并非一定要数字对应(如:ptr_fun3并非一定要与signal3对应连接)
    sigc::connection ccSg1 = sg1.connect(sigc::ptr_fun(&func1));
class mySlot: public : sigc::trackable
{
public:
int func2(char*, double)(){}
} obj;
sigc::connection ccSg2 = sg2.connect(sigc::mem_fun2(obj,&mySlot::func));
class mySg: public : sigc::trackable
{
mySg(){auto ccIter_Sg3 = sg3.connect(sigc::mem_fun(*this,&mySg::on_func));}
sigc::signal2<int, char*, double> sg3;
int on_func(char*, double)(){}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • disconnection 
    如果不需要解连接,可以不用定义sigc::connection
    ccSg1.disconnect();
ccSg2.disconnect();
  • 1
  • 2
  • 1
  • 2
  • emiting 
    // 发送信号:调用signal的emit函数
    sg1.emit("str",0.1);
sg2.emit("str",0.1);
  • 1
  • 2
  • 1
  • 2

实例:

#include <stdio.h>
#include <conio.h>
#include <cstdlib>
#include <iostream>
using namespace std; #include <sigc++/sigc++.h>
#ifdef _DEBUG
#pragma comment(lib,"sigc280d.lib")
#else
#pragma comment(lib,"sigc280.lib")
#endif // _DEBUG #define pause_wait() {std::cout << "\nPlease press any key to continue.\n";_getch();} // class
enum ObjState{Normal = 0, Hidden = 1};
class ObjectBase : public sigc::trackable
{
public:
ObjectBase(){ px = 0; py = 0; state = Normal; setConnection(); }
ObjectBase(const int &x, const int &y) :px(x), py(y){ state = Normal; setConnection(); }
~ObjectBase(){}; sigc::signal<void,const char*> putMsg; void onMoveBy(const int &x, const int &y){px += x; py += y;}
void onResize(const int &x, const int &y){px = x; py = y;}
void onSetState(ObjState s){this->state = s;}
void onPrintState()
{
if(state == Normal)
std::cout << "Normal" << std::endl;
else if(state == Hidden)
std::cout << "Hidden" << std::endl;
else
std::cout << "Error: error state value" << std::endl;
} const int& getX(){return px;}
const int& getY(){return py;}
const char* getState()
{
if(state == Normal)
return "Normal";
else if(state == Hidden)
return "Hidden";
else
return nullptr;
} private:
ObjState state;
int px;
int py; void printMsg(const char* str){std::cout << str << std::endl; }
void setConnection()
{
putMsg.connect(sigc::mem_fun(*this, &ObjectBase::printMsg));
}
}; class Control
{
public:
Control(){} sigc::signal<void, const int&, const int&> moveBy;
sigc::signal2<void, const int&, const int&> resize; // return void type, and 2 parameters
sigc::signal<void, ObjState> setState; private:
}; // print word steped by space
int printSpaceStr(const char* str)
{
int cnt = 0;
const char* p = str;
char ch;
std::cout << endl;
do
{
ch = *p;
cout << ch << ' ';
cnt++;
} while (*++p != '\0');
std::cout << endl; return cnt;
} int main(int argc, char* argv[])
{
ObjectBase obj(0, 0);
Control ctrl; sigc::signal1<int, const char*> printSS;
sigc::connection ccPrintSS = printSS.connect(sigc::ptr_fun1(&printSpaceStr));
//ccPrintSS.disconnect(); sigc::signal0<void> printState;
printState.connect(sigc::mem_fun(obj, &ObjectBase::onPrintState)); ctrl.moveBy.connect(sigc::mem_fun(obj, &ObjectBase::onMoveBy));
ctrl.resize.connect(sigc::mem_fun(obj, &ObjectBase::onResize));
auto ccIter_SetState = ctrl.setState.connect(sigc::mem_fun(obj, &ObjectBase::onSetState));
//ccIter_SetState->disconnect(); // start pro loop
PRO_Start:
while(true)
{
system("cls");
obj.putMsg.emit("Object Information");
cout << "\t Position_x: " << obj.getX() << endl;
cout << "\t Position_y: " << obj.getY() << endl;
cout << "\t State: " << obj.getState() << endl;
cout << "\n";
cout << "\t m: move object \n"
"\t r: resize object \n"
"\t s: set object state \n"
"\t p: print object state \n"
"\t a: print space word \n"
<< endl;
cout << "Input:"; char ch = getchar();
switch(ch)
{
case 'm': // move
ctrl.moveBy.emit(10,10);
break;
case 'M':
ctrl.moveBy.emit(-20,-20);
break; case 'R':
case 'r': // resize
ctrl.resize.emit(0, 0);
break; case 'P':
case 'p': // printState
goto PRO_PrintState;
break; case 's': // setState
ctrl.setState.emit(Normal);
break;
case 'S':
ctrl.setState.emit(Hidden);
break; case 'A':
case 'a':
goto RPO_PrintSpaceStr;
break; case 'Q':
case 'q': // exit
goto PRO_Exit;
break;
default:
break;
}
} PRO_PrintState:
printState.emit();
pause_wait();
goto PRO_Start; RPO_PrintSpaceStr:
printSS.emit("Sigc_Demo");
pause_wait();
goto PRO_Start; PRO_Exit:
return 0;
}

信号槽库:sigslot.h和sigc++使用的更多相关文章

  1. QT——信号槽

    结合教程,写出如下关于信号槽的代码,将教程中信号槽两种方式写入同一个界面中. #include "mainwindow.h" #include <QApplication&g ...

  2. 信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全

    关于信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全. 源码在:http://sigslot.cvs.sourcefor ...

  3. Q_OBJECT提供了信号槽机制、国际化机、RTTI 的反射能力(cpp中使用Q_OBJECT导致无法处理moc,就需要#include “moc_xxx.h”)

     只有继承了QObject类的类,才具有信号槽的能力.所以,为了使用信号槽,必须继承QObject.凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT.不管是不 ...

  4. Boost信号/槽signals2

    信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...

  5. QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类

    一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...

  6. 非Qt工程使用Qt的信号槽机制

    非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...

  7. Qt 跨UI线程的数据交换和信号-槽调用实现方案汇总

    一.目录 转载1: http://my.oschina.NET/fanhuazi/blog/737224?ref=myread 点击打开链接 转载2: http://www.qtcn.org/bbs/ ...

  8. Qt5中的信号槽

    Qt4中的信号槽 Qt4中的信号槽是通过SIGNAL,SLOT两个宏,将参数转换成字符串.Qt编译前,会从源码的头文件中提取由signal和slot声明的信号和槽的函数, 将其组成一张信号和槽对应的字 ...

  9. Pyqt 控件的信号槽事件定义方法

    转载来自:http://my.oschina.net/midnite/blog/39399 Qt采用信号槽来设定UI界面上元素动作的事件绑定.自Qt4.5开始,引入了一个新的信号槽与事件绑定的方法.界 ...

随机推荐

  1. Android面试收集录 Android布局

    1.请说出Android中的五种布局,并介绍作用? FrameLayout(堆栈布局),层叠方式显示,类似于PhotoShop上的层叠图层. LinearLayout(线性布局),将视图以水平或者垂直 ...

  2. Java密码学综述---密码学基本功能

    机密性 只有发送方与指定接收方才能理解报文的内容,监听者只能截取到加密后的报文信息,但不能还原报文的内容,做到了保密 鉴别 发送方与接收方都应该能证实通信过程所涉及的另一方,通信的另一方确实具有它们所 ...

  3. P1862 输油管道问题

    P1862 输油管道问题 题目背景 听说最近石油危机 所以想到了这题 题目描述 某石油公司计划建造一条由东向西的主要输油管道.该管道要穿过一个有n口油井的油田.从每口油井都要有一条输油管道沿最短路径( ...

  4. 《Cracking the Coding Interview》——第11章:排序和搜索——题目3

    2014-03-21 20:55 题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位.找出其中是否存在某一个值. 解法1:如果数组的元素都不重复,那么我的解法是先找出旋转的偏移量,然后进行带偏移 ...

  5. MyBatis中使用OGNL表达式与操作符

    String与基本数据类型 _parameter 自定义类型(对象) 属性名 集合 数组 array List list Map _parameter 获取集合中的一条数据 数组 array[索引] ...

  6. [洛谷P4588][TJOI2018]数学计算

    题目大意:有一个数$x$和取模的数$mod$,初始为$1$,有两个操作: $m:x=x\times m$并输出$x\% mod$ $pos:x=x/第pos次操作乘的数$(保证合法),并输出$x\%m ...

  7. 2017 多校3 hdu 6061 RXD and functions

    2017 多校3 hdu 6061 RXD and functions(FFT) 题意: 给一个函数\(f(x)=\sum_{i=0}^{n}c_i \cdot x^{i}\) 求\(g(x) = f ...

  8. 那些神奇的DP建模

    (1). 迎接仪式 思路:性质,状态1拆为2,进行匹配 (2). 数字序列 思路:转换DP方程,玄学 (3). 序列分割 思路:性质,斜率优化 (4). 经营与开发 思路:倒序,秦久韶公式 (5). ...

  9. CORS跨域cookie传递

    服务端 Access-Control-Allow-Credentials:true Access-Control-Allow-Methods:* Access-Control-Allow-Origin ...

  10. 圆盘自动机 cell

    圆盘自动机 cell 一个n-m圆盘自动机,包含n个排列成一圈的方格,它们按1至n编号.每个方格中有一个整数,范围[0,m-1] .圆盘会进行d操作,每次d操作会使得每个方格中的数同时变换,变换为与其 ...