昨天出了一个小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的更多相关文章

  1. Qt里怎么处理二进制数据

    Qt里有个专门的类QDataStream就是专门读写二进制数据的, 它与QByteArray搭配在网络编程中有奇效. 来个栗子: // write data QByteArray data; QDat ...

  2. Qt里获取目录的一个另类方法

    如果有一个文件的全路径文件名, 想获取它的路径的话, qt里我没找到比较好的办法, 都是cleanPath后, 再用QString的find, left这种函数来处理. 今天又在搞这种问题的时候, 看 ...

  3. Qt Signal and Slot

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

  4. QT里使用sqlite的问题,好多坑

    1. 我使用sqlite,开发机上好好的,测试机上却不行.后来发现是缺少驱动(Driver not loaded Driver not loaded),代码检查了又检查,发现应该是缺少dll文件(系统 ...

  5. qt里标识操作系统的宏

    qt文件里的 windows的宏是Q_WS_WIN32/*   The window system, must be one of: (Q_WS_x) MACX     - Mac OS X      ...

  6. QT中使用 slot 传递 opencv 中得Mat对象以及 使用多线程集成开源代码。

    关于 slot传递 Mat 对象 以前一直是使用 Qtimer 定时器,设定超时后读取 dialog 对象的 Mat成员实现在 UI 里显示图像,发现这样对以后集成其他面向过程的代码增加了复杂度. 所 ...

  7. 关于在Qt里让程序休眠一段时间的方法总结

    出处:http://hanzhaoxin.cnblogs.com/ Qt 为何没有提供 Sleep 论坛上不时见到有人问: Qt 为什么没有提供跨平台的 sleep 函数? 使用平台相关的 Sleep ...

  8. Qt链接网站SLOT

    void BottomToolWidget::openLink() { QString link = "http://www.baidu.com";//在.h中添加slot声明,在 ...

  9. QT里嵌入Python

    刚看到一个软件,叫做,明明是QT做的,却带了很多pyd文件(Python编译后的文件),上网一查,果然有这套相关的东西: https://doc.qt.io/archives/qq/qq23-pyth ...

随机推荐

  1. html传参数

    var request = { QueryString: function (paramName) { var url = window.location.search; paramValue = & ...

  2. MySql类似Oracle的dual虚拟表

    在mysql里也存在和oracle里类似的dual虚拟表:官方声明纯粹是为了满足select ... from...这一习惯问题,mysql会忽略对该表的引用. 你可千万注意了: select * f ...

  3. 2015.4.19 为什么footer下a的索引值那么大

    1.问题demo:为什么footer下a的索引值那么大,index不是查找兄弟级别的元素么?而且还限定了范围在footer下的a的情况下. 解决方法:alert( $("#footer a& ...

  4. 回车符(CR)与换行符(LF), '\r'和'\n'的区别

    回车”(Carriage Return)和“换行”(Line Feed)这两个概念的来历和区别.在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33,Linux/Unix下 ...

  5. 【转载】使用Pandas对数据进行筛选和排序

    使用Pandas对数据进行筛选和排序 本文转载自:蓝鲸的网站分析笔记 原文链接:使用Pandas对数据进行筛选和排序 目录: sort() 对单列数据进行排序 对多列数据进行排序 获取金额最小前10项 ...

  6. UML--PowerDesigner使用小结

    以前只是觉得.边看书.边撸代码.效果还不错.现在发现.边看书.边设计类图.效果也不错哈.最好书上有类图.自己刚开始可以依葫芦画瓢. 用到的工具是PowerDesigner... 先新建一个类图.文件& ...

  7. 如何查看、修改Linux的系统时间

    如题: 如何修改Linux的系统时间? date -s 05/27/2011 date -s 10:24:00 clock -w 就这三条命令就OK了! 查看/修改Linux时区和时间 一.时区 1. ...

  8. CSS3 @media 查询

    @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的. 媒体查询包含了一个媒体类型和CSS3规范中描述的包含一个或多个表达式的媒体属性, ...

  9. tornado 第二种路由方法(装饰器)

    #!/usr/bin/env python # _*_coding:utf-8 _*_ import tornado.ioloop import tornado.web application = t ...

  10. 无密钥登录的自动脚本实现(ssh-copy-id、expect免交互输入脚本)

    感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正! 如有转载,请保留源作者博客信息. Better Me的博客:blog.csdn.net/tantexian 如需 ...