昨天出了一个小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. 记录-div绝对定位针对手机浏览器的区别

    最近搞个wap ,有一个需求就是一些文字描述定位到一张图片上的某个地方,按照以往的方式直接通过定位div position: absolute; PC chrome 模拟手机显示没问题! 但是,在ip ...

  2. 深入理解javascript原型和闭包(13)-【作用域】和【上下文环境】

    上文简单介绍了作用域,本文把作用域和上下文环境结合起来说一下,会理解的更深一些. 如上图,我们在上文中已经介绍了,除了全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了.而不 ...

  3. [NHibernate]延迟加载

    目录 写在前面 文档与系列文章 延迟加载 一个例子 总结 写在前面 上篇文章介绍了多对多关系的关联查询的sql,HQL,Criteria查询的三种方式.本篇文章将介绍nhibernate中的延迟加载方 ...

  4. Javascript的setTimeOut()和setInterval()的定时器用法

    Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请 ...

  5. App提交iTunes Connect,"二进制无效"问题解决方案。

    昨天提交打包提交App,将包上传到iTunes Connect之后,以为就能发布了,便点击构建版本,发现没有刚刚上传的包,于是就点击"预发行"看一下,会看到"已上传&qu ...

  6. 【bzoj3531】 [SDOI2014]旅行

    题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们 ...

  7. 《征服 C 指针》摘录5:函数形参 和 空的下标运算符[]

    一.函数的形参的声明 C 语言可以像下面这样声明函数的形参: void func(int a[]) {     // ... } 对于这种写法,无论怎么看都好像要向函数的参数传递数组. 可是,在 C ...

  8. PCA本质和SVD

    一.一些概念 线性相关:其中一个向量可以由其他向量线性表出. 线性无关:其中一个向量不可以由其他向量线性表出,或者另一种说法是找不到一个X不等于0,能够使得AX=0.如果对于一个矩阵A来说它的列是线性 ...

  9. 在OSX和Windows版本Docker上运行GUI程序

    看到很多人在Docker问题区讨论:如何在OS X和Windows的Docker上运行GUI程序, 随手记录几个参考资料: https://github.com/docker/docker/issue ...

  10. ASP.NET Core--条件处理程序中的依赖注入

    翻译如下: 在配置期间(使用依赖注入),授权处理程序必须在服务集合中注册. 假设您有一个在授权处理程序中要解析规则的仓储库,并且该仓储库已在服务集合中注册. 授权将在构造函数还原并注入. 例如,如果你 ...