用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. POJ3246

    Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same ...

  2. 51Nod 1680 区间求和 树状数组

    题意: 给出一个长度为\(n\)的数列\(A_i\),定义\(f(k)\)为所有长度大于等于\(k\)的子区间中前\(k\)大数之和的和. 求\(\sum_{k=1}^{n}f(k) \; mod \ ...

  3. imageX.exe

    imageX 编辑ImageX 是一个命令行工具,原始设备制造商 (OEM) 和公司可以使用它来捕获.修改和应用基于文件的磁盘映像以进行快速部署.ImageX 可以使用 Windows 映像 (.wi ...

  4. Visual Studio Emulator for Android 折腾记

    想用虚拟机调试Android项目,于是想到了MS免费提供的 Visual Studio Emulator for Android,这玩意价格免费量又足,N久之前试用过,速度杠杠的! 安装包很小,不到4 ...

  5. leetcode 【 Intersection of Two Linked Lists 】python 实现

    题目: Write a program to find the node at which the intersection of two singly linked lists begins. Fo ...

  6. spring 笔记2:Spring MVC : Did not find handler method for 问题的解决

    日志显示为: Looking up handler method for path /***Did not find handler method for [/***]No mapping found ...

  7. 问题:JFinal框架使用FreeMarker渲染视图报错

    本人用的是JFinal-3.4. 问题描述: 在JFinal框架中使用FreeMarker渲染视图时,报 Caused by: java.lang.ClassNotFoundException: fr ...

  8. day02-python基础2

    操作 列表是用来存储一组数据,可以实现对列表中元素的增删改查等操作. 转换: list(string):把字符串转为列表 声明: 列表使用方括号 查询: 根据元素下标获取列表中元素的值 切片: [0: ...

  9. 【志银】NYOJ《题目860》又见01背包

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860 方法一:不用滚动数组(方法二为用滚动数组,为方法一的简化) 动态规划分析:最少要拿总 ...

  10. c++知识点总结--静态与动态类型

    对象的静态类型(static type),就是它在程序中被声明时所采用的类型 对象的动态类型(dynamic type)是指“目前所指对象的类型”   vitual 函数是动态绑定而来,调用一个vir ...