一、正文

目前正在做一个视频处理相关的项目。项目的技术栈是这样的,UI层采用Qt来实现基本的数据展示和交互,底层音视频采用的是一套基于FFmpeg的视频处理框架。这是一套类似Microsoft Media Foundation的处理框架,采用管道流进行架构,解复用、解码、复用、编码及用户自定义操作都采用Filter组件来实现,灵活度和可扩展性都比较好。(基本上常用音视频处理框架都采用了这一架构,如Microsoft Media Foundation, DirectShow Filter, gstreamer

项目要求视频在处理的过程中,实时计算出当前的进度并展示在UI上,方便用户随时查看处理进度。想象中的处理方式是:负责Progress的Filter每一次计算进度的时候都发送一个信号给UI,方便更新进度条。于是ProgressFilter的实现大致如下:

template<typename DataType>
class ProgressFilter : public ins::MediaFilter<DataType,DataType>, public QObject{
Q_OBJECT
public:
~ProgressFilter() = default; ProgressFilter(uint64_t totalFrames = 1) :
mCurrentFrameIndex(0),
mTotalFrames(totalFrames) { } bool Init(ins::MediaContext* ctx) {
return this->next_filter_->Init(ctx);
} bool Filter(ins::MediaContext* ctx, const DataType& data) {
double progress = std::min((double)(++mCurrentFrameIndex) / mTotalFrames, 0.99);
emit progressChanged(progress);
return this->next_filter_->Filter(ctx, data);
} void Close(ins::MediaContext* ctx) {
this->next_filter_->Close(ctx);
} void Notify(ins::MediaContext* ctx, const ins::MediaNotify& notify) {
if (notify.type == ins::kNotifyEOF) {
double progress = std::min(std::ceil((double)mCurrentFrameIndex / mTotalFrames), 1.0);
emit progressChanged(progress);
}
this->next_filter_->Notify(ctx, notify);
}
signals:
void progressChanged(double progress);
private:
uint64_t mCurrentFrameIndex;
uint64_t mTotalFrames;
};

然而编译的时候却提示报错:

错误提示已经很显然了,Q_OBJECT宏不支持C++模板类。Qt中一个类如果需要支持信号槽机制,那么必须要加一个Q_OBJECT做预处理。而项目当前使用的这套视频处理框架又大量使用了模板技术,改源码显然不大现实。那么就没有办法了吗?网上搜了一下就找到了一个解决办法。那就是实现一个普通的中间类,在这个类中定义信号槽。然后再让模板类继承这个中间类即可。所以我们实现一个中间类:

class Proxy : public QObject {
Q_OBJECT public:
explicit Proxy(QObject *parent = 0) : QObject(parent) {} signals:
void progressChanged(double progress);
}; template<typename DataType>
class ProgressFilter : public ins::MediaFilter<DataType,DataType>, public Proxy {
public:
~ProgressFilter() = default;
...... }

这样,我们的模板类就可以正常使用信号槽机制了。

二、参考链接

1. https://stackoverflow.com/questions/4397478/qt-templated-q-object-class

2. https://stackoverflow.com/questions/4238204/is-it-possible-to-mix-template-derived-c-classes-with-qts-q-object

C++模板类与Qt信号槽混用的更多相关文章

  1. QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类

    一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...

  2. Qt信号槽的一些事(第一次知道信号还有返回值,以及Qt::UniqueConnection)

    注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...

  3. QT信号槽详解

    1         QT信号槽详解 1.1  信号和槽的定义 信号是触发信号,例如按钮的点击触发一个clicked信号,槽是用来接收信号,并处理信号,相当于信号响应函数.一个信号可以关联多个槽函数,信 ...

  4. Qt信号槽的一些事 Qt::带返回值的信号发射方式

    一般来说,我们发出信号使用emit这个关键字来操作,但是会发现,emit并不算一个调用,所以它没有返回值.那么如果我们发出这个信号想获取一个返回值怎么办呢? 两个办法:1.通过出参形式返回,引用或者指 ...

  5. Qt信号槽的一些事

    注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...

  6. Qt信号槽-原理分析

    目录 一.问题 二.Moc 1.变量 2.Q_OBJECT展开后的函数声明 3.自定义信号 三.connect 四.信号触发 1.直连 2.队列连接 五.总结 六.推荐阅读 一.问题 学习Qt有一段时 ...

  7. (文字版)Qt信号槽源码剖析(三)

    大家好,我是IT文艺男,来自一线大厂的一线程序员 上节视频给大家讲解了Qt信号槽的Qt宏展开推导:今天接着深入分析,进入Qt信号槽源码剖析系列的第三节视频. Qt信号槽宏推导归纳 #define si ...

  8. QT源码之Qt信号槽机制与事件机制的联系

    QT源码之Qt信号槽机制与事件机制的联系是本文要介绍的内容,通过解决一个问题,从中分析出的理论,先来看内容. 本文就是来解决一个问题,就是当signal和slot的连接为Qt::QueuedConne ...

  9. Qt信号槽源码剖析(一)

    大家好,我是IT文艺男,来自一线大厂的一线程序员 大家在使用Qt开发程序时,都知道怎么使用Qt的信号槽,但是Qt信号槽是怎么工作的? 大部分人仍然不知道:也就是说大家只知道怎么使用,却不知道基于什么原 ...

随机推荐

  1. Redis进阶实践之十四 Redis-cli命令行工具使用详解第一部分

    一.介绍       redis学了有一段时间了,以前都是看视频,看教程,很少看官方的东西.现在redis的东西要看的都差不多看完了.网上的东西也不多了.剩下来就看看官网的东西吧,一遍翻译,一遍测试. ...

  2. 浅谈 Glide - BitmapPool 的存储时机 & 解答 ViewTarget 在同一View显示不同的图片时,总用同一个 Bitmap 引用的原因

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  3. Android开发之组件

    Android应用程序由组件组成,组件是可以解决被调用的基本功能模块.Android系统利用组件实现程序内部或程序间的模块调用,以解决代码复用问题,这是Android系统非常重要的特性.在程序设计时, ...

  4. linux 分布式文件系统

    分布式文件系统(DFS) 指文件系统管理的物理存储资源不一定直接连接在本地节点上 而是通过计算机网络与节点相连 分布式文件系统的设计基于客户机/服务器模式 一个典型的网络可能包括多个多个用户访问的服务 ...

  5. Sublime Text [Decode error - output not utf-8]

    改Sublime Text的python build的设置.将其编码设置为cp936. 打开Python.sublime-build文件,并添加”encoding”:”cp936″这一行,保存即可 S ...

  6. PHPmysqli的 其他函数 从数据库中读出数据并且打印出来

    <?php // 认识其他mysqli其他函数 header( 'Content-Type:text/html;charset=utf-8 '); require 'prepareSrarmen ...

  7. An internal error occurred during: "Building workspace". java.lang.StackOverflowError

    1 错误描述 2 错误原因 由上述描述可以,MyEclipse可用内存不足,导致堆内存溢出 3 解决办法 修改MyEclipse内存设置 #utf8 (do not remove) #utf8 (do ...

  8. es6的新特性--模板字符串

    这几天简单看了一下深入浅出es6这本书,感觉特实用,学习了一个新特性---模板字符串在项目开发中,拼接字符串是不可缺少的,动态创建dom元素以及js操作数据都要拼接字符串,在es6出来之前,我们都通常 ...

  9. Windows10 + Matlab2013 mex C++ 调用gsl

    最前面啰嗦一句,matlab默认编译c的编译器有点奇怪,会出现引用.h却找不到相应函数的问题,解决方法是把.c全部都改成.cpp!血的教训! 下面进入正题~~ 由于Matlab调用的C函数中引用了GS ...

  10. 2.3 InnoDB 体系架构

    下图简单显示了InnoDB的存储引擎的体系架构,从图可见,InnoDB储存引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责如下工作: 维护所有进程/线程需要访问的多个内部数据结构 缓存磁 ...