C++模板类与Qt信号槽混用
时间:2022-05-07
本文章向大家介绍C++模板类与Qt信号槽混用,主要内容包括一、正文、二、参考链接、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
一、正文
目前正在做一个视频处理相关的项目。项目的技术栈是这样的,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
- 一个小实验,验证一个大受欢迎数据库的容器化
- 【选择题】Java基础测试四(15道)
- GO语言并发编程之互斥锁、读写锁详解
- GO语言标准错误处理机制error用法实例
- spring框架复习大纲【面试+提高】
- Go语言中的Array、Slice、Map和Set使用详解
- go的websocket实现原理与用法详解
- go语言base64加密解密的方法
- Go语言轻量级线程Goroutine用法实例
- Go语言的队列和堆栈实现方法
- Go语言使用sort包对任意类型元素的集合进行排序的方法
- TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现
- [go语言]吐槽:怎么样实现支持并发访问的数据集合更好?
- 利用缓冲信道来实现网游帐号验证消息的分发和等待
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android-ViewModel和LiveData使用详解
- 详解Android开发录音和播放音频的步骤(动态获取权限)
- Android自定义带圆角的ImageView
- 关于Kotlin写界面时诸多控件的点击事件
- Android webview注入JS代码 修改网页内容操作
- Kotlin 使用高阶函数实现回调方式
- Android WebView通过动态的修改js去拦截post请求参数实例
- Android使用Kotlin实现多节点进度条
- Android中webView加载H5绑定cookie实例
- 解决Android webview设置cookie和cookie丢失的问题
- Android实现清除单个域名的cookie
- Android实现触发html页面的Button控件点击事件方式
- webview添加参数与修改请求头的user-agent实例
- android webview获取html代码和根据id获取value实例
- pip 安装MySQL-python:EnvironmentError: mysql_config not found