Qt里的slot
昨天出了一个小bug, 一直调都没调出来, 今天仔细看了下, 发现出错的原因了.
我在用osgEarth的时候, 用到一个类MapCatalogWidget, 觉得它不够用, 就把这个类给改了下, 添加了个slot:
public slots:
void addViewpoint(Viewpoint& vp);
这里由于MapCatalogWidget类自己已经添加了命名空间的引用, 所以想当然的在这里就没有使用 osgEarth::Viewpoint 这样的方式.
添加信号, 槽:
connect(manip, SIGNAL(viewpoint(osgEarth::Viewpoint&)),
vpCatalog, SLOT(addViewpoint(osgEarth::Viewpoint&)));
结果添加完后, 怎么也不响应, 而且输出窗口出还出现这么一句话:
Object::connect: No such slot osgEarth::QtGui::MapCatalogWidget::addViewpoint(osgEarth::Viewpoint&)
明明自己写了啊, 怎么就找不着呢....
经过分析, 觉得应该是出在moc处理slot上, 查看了下moc_MapCatalogWidget.cpp文件, 就发现了问题:
static const char qt_meta_stringdata_osgEarth__QtGui__MapCatalogWidget[] = {
"osgEarth::QtGui::MapCatalogWidget\0\0"
"onMapChanged()\0onSelectionChanged()\0"
"item,col\0onTreeItemDoubleClicked(QTreeWidgetItem*,int)\0"
"onTreeItemChanged(QTreeWidgetItem*,int)\0"
"onTreeSelectionChanged()\0pos\0"
"onTreeNodeRClick(QPoint)\0editModel()\0"
"vp\0addViewpoint(Viewpoint&)\0delViewpoint()\0"
};
void osgEarth::QtGui::MapCatalogWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Q_ASSERT(staticMetaObject.cast(_o));
MapCatalogWidget *_t = static_cast<MapCatalogWidget *>(_o);
switch (_id) {
case 0: _t->onMapChanged(); break;
case 1: _t->onSelectionChanged(); break;
case 2: _t->onTreeItemDoubleClicked((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
case 3: _t->onTreeItemChanged((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
case 4: _t->onTreeSelectionChanged(); break;
case 5: _t->onTreeNodeRClick((*reinterpret_cast< const QPoint(*)>(_a[1]))); break;
case 6: _t->editModel(); break;
case 7: _t->addViewpoint((*reinterpret_cast< Viewpoint(*)>(_a[1]))); break;
case 8: _t->delViewpoint(); break;
default: ;
}
}
}
可以看出这里moc解析slot后, 会得到这样一组字符串数组, 然后用数组中的"特殊"字符串的索引来做case, 以映射到对应的函数中.
这里之所以说是特殊字符串, 你可以仔细看看那个字符串数组, 它是分为两个部分, 用"\0\0"分隔开, 第一部分是类名, 第二部分是函数名, 这里函数如果带参数的话, 参数是放在函数名前的, 函数名和参数名都用"\0"来分隔的 (这里真心佩服qt的团队, 这种办法也想得出来.....).
看完这里的代码, 其实connect函数干的事情应该也能分析出个大概:
1. 把SIGNAL和SLOT宏的参数转换成字符串
2. 在实际调用的时候, Qt会将发出的信息, 转换得到匹配的槽
3. 再转到槽类中, 用字符串匹配到对应的函数来执行.
connect(manip, SIGNAL(viewpoint(Viewpoint&)),
vpCatalog, SLOT(addViewpoint(Viewpoint&)));
这里要注意一下, 两个域约束符号要去都要去, 否则运行时, qt会在输出窗口中提示你:
QObject::connect: Incompatible sender/receiver arguments
UIManipulator::viewpoint(osgEarth::Viewpoint&) --> osgEarth::QtGui::MapCatalogWidget::addViewpoint(Viewpoint&)
问题了解了, 解决就比较简单了!
我这里只要把MapcatalogWidget中的槽函数声明加上域约束符就OK了.
public slots:
void addViewpoint(osgEarth::Viewpoint& vp);
希望能帮上有同样问题的朋友.
Qt里的slot的更多相关文章
- Qt里怎么处理二进制数据
Qt里有个专门的类QDataStream就是专门读写二进制数据的, 它与QByteArray搭配在网络编程中有奇效. 来个栗子: // write data QByteArray data; QDat ...
- Qt里获取目录的一个另类方法
如果有一个文件的全路径文件名, 想获取它的路径的话, qt里我没找到比较好的办法, 都是cleanPath后, 再用QString的find, left这种函数来处理. 今天又在搞这种问题的时候, 看 ...
- Qt Signal and Slot
Qt4中的信号槽 Qt4中的信号槽是通过SIGNAL,SLOT两个宏,将参数转换成字符串.Qt编译前,会从源码的头文件中提取由signal和slot声明的信号和槽的函数, 将其组成一张信号和槽对应的字 ...
- QT里使用sqlite的问题,好多坑
1. 我使用sqlite,开发机上好好的,测试机上却不行.后来发现是缺少驱动(Driver not loaded Driver not loaded),代码检查了又检查,发现应该是缺少dll文件(系统 ...
- qt里标识操作系统的宏
qt文件里的 windows的宏是Q_WS_WIN32/* The window system, must be one of: (Q_WS_x) MACX - Mac OS X ...
- QT中使用 slot 传递 opencv 中得Mat对象以及 使用多线程集成开源代码。
关于 slot传递 Mat 对象 以前一直是使用 Qtimer 定时器,设定超时后读取 dialog 对象的 Mat成员实现在 UI 里显示图像,发现这样对以后集成其他面向过程的代码增加了复杂度. 所 ...
- 关于在Qt里让程序休眠一段时间的方法总结
出处:http://hanzhaoxin.cnblogs.com/ Qt 为何没有提供 Sleep 论坛上不时见到有人问: Qt 为什么没有提供跨平台的 sleep 函数? 使用平台相关的 Sleep ...
- Qt链接网站SLOT
void BottomToolWidget::openLink() { QString link = "http://www.baidu.com";//在.h中添加slot声明,在 ...
- QT里嵌入Python
刚看到一个软件,叫做,明明是QT做的,却带了很多pyd文件(Python编译后的文件),上网一查,果然有这套相关的东西: https://doc.qt.io/archives/qq/qq23-pyth ...
随机推荐
- css3动画简介以及动画库animate.css的使用
在这个年代,你要是不懂一点点css3的知识,你都不好意思说你是个美工.美你妹啊,请叫我前端工程师好不好.呃..好吧,攻城尸...呵呵,作为一个攻城尸,没有点高端大气上档次的东西怎么能行呢,那么css3 ...
- mysql的DISABLE/ENABLE KEYS
有一个表 tbl1 的结构如下: CREATE TABLE `tbl1` ( `id` int(10) unsigned NOT NULL auto_increment, `name` char(20 ...
- 6个变态的C语言Hello World程序
6个变态的C语言Hello World程序 下面的六个程序片段主要完成这些事情: 输出Hello, World 混乱C语言的源代码 下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C+ ...
- mac brew install redis 报错
mac brew install redis 报错 /usr/local/opt/php55/bin/phpize /usr/local/opt/php55/bin/phpize: line 61: ...
- getRealPath("/")弃用
用request.getSession().getServletContext().getRealPath("/");替换getRealPath("/"):
- this a a mark down test
*** this is title ''' code '''
- 一款全兼容的播放器 videojs
[官网]http://www.videojs.com/ videojs就提供了这样一套解决方案,他是一个兼容HTML5的视频播放工具,早期版本兼容所有浏览器,方法是:提供三个后缀名的视频,并在不支持h ...
- ABAP 传入数据到EXCEL自编函数
DATA: excel TYPE ole2_object, workbook TYPE ole2_object, sheet TYPE ole2_object, ...
- ASP.NET知识总结(1.网络传输层)
1.网络传输层 1应用层(HTTP.FTP.SMTP)报文Message 2传输层(TCP.UDP)报文段Segment,为运行在不同主机上的应用程序进程间提供数据 传输服务.通过套接字(Socket ...
- linux 内核与用户空间通信之netlink使用方法
转自:http://blog.csdn.net/haomcu/article/details/7371835 Linux中的进程间通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&a ...