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 ...
随机推荐
- 使用Spring和SpringMVC管理bean时要注意的一个小细节
最近一直在做毕业设计...用到了Shiro和SpringMVC..用过shiro的朋友都知道shiro需要自己去写Realm,然后把Realm注入到SecurityManager中.而Security ...
- 再谈 $* 和 $@ 在 Bash 中的表现
除非特别说明,本文中出现的 Shell 均指 Bash 4.3.首先说一个基础知识:Shell 中的变量在展开成值(Parameter Expansion)之后,这个值在某些上下文(Context)中 ...
- [Kerberos] Java client访问kerberos-secured cluster
使用java client访问kerberos-secured cluster,最重要的是先从admin那里拿到可用的keytab文件,用来作认证.接下来就是调整连接的配置.以下先用连接hdfs为例进 ...
- 【荐】PHP Session和Cookie,Session阻塞,Session垃圾回收,Redis共享Session,不推荐Memcached保存Session
什么是 Session 在 web 应用开发中,Session 被称为会话.主要被用于保存某个访问者的数据. 由于 HTTP 无状态的特点,服务端是不会记住客户端的,对服务端来说,每一个请求都是全新的 ...
- update语句关联表更新
UPDATE dbo.NodeInstance SET OrderNumber=temp.OrderNo FROM dbo.NodeInstance ins,dbo.NodeTemplate temp ...
- 引用项目外dll时不显示注释的解决方案
在引用项目外的dll时,显示类库中的注释可按以下步骤: 方法或变量用summary添加注释,如: /// <summary>发送post请求 /// < ...
- php之JavaScript
JS对于大小写敏感 作用:增加跟html页面的交互性. 应用:验证表单.创建cookies(可插入html页面的编程代码)js插入页面后可由所有现代的浏览器执行.应用于<body>< ...
- python用二进制读取文件
python二进制读取文件 很多时候,都需要用到二进制读取文件.毕竟很多信息不是以文本的形式存储.例如:图片,音乐等等.这些东西都是有规则的二进制文件. 在python中,二进制读取采用rb的方式. ...
- 安装rabbitmq
安装配置epel源 $ rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm 安装erlan ...
- python 3.x urllib学习
urllib.request import urllib.request as ur url='http://ie.icoa.cn' user_agent = 'Mozilla/4.0 (compat ...