信号槽库:sigslot.h和sigc++使用
用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++使用的更多相关文章
- QT——信号槽
结合教程,写出如下关于信号槽的代码,将教程中信号槽两种方式写入同一个界面中. #include "mainwindow.h" #include <QApplication&g ...
- 信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全
关于信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全. 源码在:http://sigslot.cvs.sourcefor ...
- Q_OBJECT提供了信号槽机制、国际化机、RTTI 的反射能力(cpp中使用Q_OBJECT导致无法处理moc,就需要#include “moc_xxx.h”)
只有继承了QObject类的类,才具有信号槽的能力.所以,为了使用信号槽,必须继承QObject.凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT.不管是不 ...
- Boost信号/槽signals2
信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...
- QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...
- 非Qt工程使用Qt的信号槽机制
非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...
- Qt 跨UI线程的数据交换和信号-槽调用实现方案汇总
一.目录 转载1: http://my.oschina.NET/fanhuazi/blog/737224?ref=myread 点击打开链接 转载2: http://www.qtcn.org/bbs/ ...
- Qt5中的信号槽
Qt4中的信号槽 Qt4中的信号槽是通过SIGNAL,SLOT两个宏,将参数转换成字符串.Qt编译前,会从源码的头文件中提取由signal和slot声明的信号和槽的函数, 将其组成一张信号和槽对应的字 ...
- Pyqt 控件的信号槽事件定义方法
转载来自:http://my.oschina.net/midnite/blog/39399 Qt采用信号槽来设定UI界面上元素动作的事件绑定.自Qt4.5开始,引入了一个新的信号槽与事件绑定的方法.界 ...
随机推荐
- ABAP自定义截取字符串长度函数
SAP 中strlen()只能计算字符串的个数,不能计算含有中文字符串的长度,如字符串“SAP大波霸”,strlen('SAP大波霸') = 6,其实真实长度为3+3*2 = 9.我们可以通过cl_a ...
- 分布式爬虫:使用Scrapy抓取数据
分布式爬虫:使用Scrapy抓取数据 Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘. ...
- Flume是什么
分布式流式实时收集日志文件系统,便于实时在线的流式计算,常配合 Storm 和 spark streming 使用. Flume is a distributed分布式的, reliable可靠的, ...
- PHP.19-验证码生成
生成验证码 思路:先定义验证码函数getCode() //绘制验证码 $num = 4; //字符长度 getCode($num, 2); 1.创建画布,分配颜色 imagecreatetruecol ...
- mongo创建数据库和用户
1.linux安装mongo conf文件配置: 配置文件: dbpath=/home/data/mongodb/mongodb logpath=/home/data/logs/mongodb.log ...
- 远程 RADIUS 服务器组
远程 RADIUS 服务器组 远程 RADIUS 服务器组是包含一个或多个 RADIUS 服务器的已命名的组.IAS 用作 RADIUS 请求消息的 RADIUS 代理时,必须指定远程 RADIUS ...
- typeAliasesPackage 配置
mybatis 的 xml 文件中需要写类的全限定名,较繁琐,可以配置自动扫描包路径给类配置别名,有两种配置方式. 方式一: mybatis-config.xml 中配置 <typeAliase ...
- NGUI-使用UILabel呈现图片和不同格式的文字
1.可以使用BBCode标记 [b]Bold[/b] 粗体[i]italic[/i] 斜体[u]underli ...
- $this和self、parent这三个关键词分别代表什么?在哪些场合下使用?
$this:当前对象 self: 当前类 parent: 当前类的父类 $this在当前类中使用,使用->调用属性和方法. self也在当前类中使用,不过需要使用::调用. 静态属性,不能在类里 ...
- MapReduce架构
主从结构 主节点:JobTracker(一个) 从节点:TaskTrackers(多个) JobTracker: 接收客户提交的计算任务 把计算任务分配给TaskTrackers执行 监控TaskTr ...