当前位置: 首页 > news >正文

Qt开发⑪Qt网络+Qt音视频_使用实操

目录

1. Qt 网络

1.1 UDP Socket

1.2 TCP Socket

1.3 HTTP Client

2. Qt 音视频

2.1 Qt 音频

2.2 Qt 视频

本篇完。


1. Qt 网络

和多线程类似,Qt 为了支持跨平台, 对网络编程的 API 也进行了重新封装。

        实际 Qt 开发中进行网络编程,也不一定使用 Qt 封装的网络 API,也有一定可能使用的是系统原生 API 或者其他第三方框架的 API。 

        在进行网络编程之前,需要在项目中的 .pro 文件中添加 network 模块。添加之后要手动编译一下项目,使 Qt Creator 能够加载对应模块的头文件。

为什么 Qt 要划分出这些模块呢?

        因为Qt 本身是一个非常庞大,包罗万象的框架。如果把所有的 Qt 的功能都放到一起,既是我们就只是写一个简单的 hello world,那此时生成的可执行程序也会非常庞大(就包含了大量并没有使用的功能)。

模块化处理:

  • 其它的功能分别封装成不同的模块。
  • 默认情况下,这些额外的模块不会参与编译。
  • 需要在 .pro 文件中引入对应的模块,才能把对于功能给编译加载进来。

1.1 UDP Socket

(1)核心 API 概览

主要的类有两个:QUdpSocket 和 QNetworkDatagram

QUdpSocket 表示一个 UDP 的 socket 文件

QNetworkDatagram 表示一个 UDP 数据报


(2)回显服务器

1. 创建界面,包含一个 QListWidget 用来显示消息

2. 创建 QUdpSocket 成员

不能直接添加头文件,否则无法编译通过,需要先添加网络模块。

修改 widget.h

修改 widget.cpp,完成 socket 后续的初始化

        一般来说,要先连接信号槽,再绑定端口。如果顺序反过来,可能会出现端口绑定好了之后,请求就过来了,此时还没来得及连接信号槽,那么这个请求就有可能错过了。


实现 processRequest,完成处理请求的过程

  • 读取请求并解析
  • 根据请求计算响应
  • 把响应写回到客户端


实现 process 函数

由于我们此处是实现回显服务器,所以 process 方法中并没有包含实质性的内容。

此时,服务器程序编写完毕,但是直接运行还看不出效果,还需要搭配客户端来使用。


(3)回显客户端

创建界面,包含一个 QLineEdit、QPushButton、QListWidget

  • 先使用水平布局把 QLineEdit 和 QPushButton 放好,并设置这两个控件的垂直方向的 sizePolicy 为 Expanding。
  • 再使用垂直布局把 QListWidget 和上面的水平布局放好。
  • 设置垂直布局的 layoutStretch 为 5,1(这个尺寸比例可以根据个人喜好微调)。


在 widget.cpp 中,先创建两个全局常量,表示服务器的 IP 和端口

端口到本质上是一个 2 字节的无符号整数。

        quint16:本质上就是一个 unsigned short(虽然 short 通常都是 2 个字节,但是 C++ 标准中没有明确规定这一点,只是说 short 不应该少于 2 个字节)。


创建 QUdpSocket 成员:

修改 widget.h,定义成员


修改 widget.cpp,初始化 socket


给发送按钮 slot 函数,实现发送请求


再次修改 Widget 的构造函数,通过信号槽来处理服务器的响应


最终执行效果

客户端服务器测试的基本原则:一定是先启动服务器,后启动客户端。

启动多个客户端都可以正常工作,但是不能在界面选择直接运行,否则会覆盖上一个客户端。


1.2 TCP Socket

(1)核心 API 概览

核心类是两个:QTcpServer 和 QTcpSocket

QTcpServer 用于监听端口,和获取客户端连接。

QTcpSocket 用户客户端和服务器之间的数据交互。

QByteArray 用于表示一个字节数组,可以很方便的和 QString 进行相互转换。

例如:

  • 使用 QString 的构造函数即可把 QByteArray 转成 QString
  • 使用 QString 的 toUtf8 函数即可把 QString 转成 QByteArray

(2)回显服务器

创建界面,包含一个 QListWidget,用于显示收到的数据


创建 QTcpServer 并初始化

修改 widget.h,添加 QTcpServer 指针成员


修改 widget.cpp,实例化 QTcpServer 并进行后续初始化操作

  • 设置窗口标题
  • 实例化 TCP server(父元素设为当前控件,会在父元素销毁时被一起销毁)
  • 通过信号槽,处理客户端建立的新连接
  • 监听端口


继续修改 widget.cpp,实现处理连接的具体方法 processConnection

  • 获取到新的连接对应的 socket
  • 通过信号槽,处理收到请求的情况
  • 通过信号槽,处理断开连接的情况

        上述代码其实不够严谨,但在这里作为回显服务器已经够了。实际在使用 TCP 的过程中,TCP 是面向字节流的,一个完整的请求可能会分成多段字节数组进行传输。虽然 TCP 已经帮我们处理了很多棘手的问题,但是 TCP 本身并不负责区分从哪里到哪里是一个完整的应用层数据(粘包问题)。

        更严谨的做法:每次收到的数据都给它放到一个字节数组缓冲区中,并且提前约定好应用层协议的格式(分隔符 / 长度 / 其他办法),再按照协议格式对缓冲区数据进行更细致的解析处理。


实现 process 方法,实现根据请求处理响应

由于此处是实现回显服务器,所以 process 方法中并没有包含实质性的内容。

此时,服务器程序编写完毕,但是直接运行还看不出效果,还需要搭配客户端来使用。


(3)回显客户端

创建界面,包含一个 QLineEdit、QPushButton、QListWidget

  • 先使用水平布局把 QLineEdit 和 QPushButton 放好,并设置这两个控件的垂直方向的 sizePolicy 为 Expanding
  • 再使用垂直布局把 QListWidget 和上面的水平布局放好
  • 设置垂直布局的 layoutStretch 为 5,1(这个尺寸比例可以根据个人喜好微调)


创建 QTcpSocket 并实例化

修改 widget.h,创建成员


修改 widget.cpp,对 QTcpSocket 进行实例化

  • 设置窗口标题
  • 实例化 socket 对象(父元素设为当前控件,会在父元素销毁时被一起销毁)
  • 和服务器建立连接
  • 等待并确认连接是否出错


修改 widget.cpp,给按钮增加点击的 slot 函数,实现发送请求给服务器


修改 widget.cpp 中的 Widget 构造函数,通过信号槽处理收到的服务器的响应

先启动服务器,再启动客户端(可以启动多个),最终执行效果:

        由于我们使用信号槽处理同一个客户端的多个请求,不涉及到循环,也就不会使客户端之间相互影响了。


1.3 HTTP Client

进行 Qt 开发时,和服务器之间的通信很多时候也会用到 HTTP 协议。

  • 通过 HTTP 从服务器获取数据
  • 通过 HTTP 向服务器提交数据

(1)核心 API

关键类主要是三个:QNetworkAccessManager、QNetworkRequest、QNetworkReply。

QNetworkAccessManager 提供了 HTTP 的核心操作:

QNetworkRequest 表示一个 HTTP 请求(不含 body)。

        如果需要发送一个带有 body 的请求(比如 post),会在 QNetworkAccessManager 的 post 方法中通过单独的参数来传入 body。

其中的 QNetworkRequest::KnownHeaders 是一个枚举类型,常用取值:

QNetworkReply 表示一个 HTTP 响应,这个类同时也是 QIODevice 的子类。

此外,QNetworkReply 还有一个重要的信号 finished 会在客户端收到完整的响应数据之后触发。


(2)给服务器发送一个 GET 请求

创建界面,包含一个 QLineEdit、QPushButton

  • 先使用水平布局把 QLineEdit 和 QPushButton 放好,并设置这两个控件的垂直方向的 sizePolicy 为 Expanding。
  • 再使用垂直布局把 QPlainTextEdit 和上面的水平布局放好(QPlainTextEdit 的 readOnly 设为 true)。
  • 设置垂直布局的 layoutStretch 为 5,1(这个尺寸比例可以根据个人喜好微调)。

        注意:此处建议使用 QPlainTextEdit,而不是 QTextEdit。主要是因为 QTextEdit 要进行富文本解析,最终显示的结果就不是原始的 HTML 了,如果得到的 HTTP 响应体积很大,会导致界面渲染缓慢甚至被卡住。


修改 widget.h,创建 QNetworkAccessManager 属性


修改 widget.cpp,创建实例


编写按钮的 slot 函数,实现发送 HTTP 请求功能

执行程序,观察效果:

发送 POST 请求代码也是类似,使用 manager->post() 即可。

        实际开发中,HTTP Client 获取到的的数据也不一定非得是 HTML,更大的可能性是客户端开发和服务器开发约定好交互的数据格式。按照约定的格式,客户端拿到之后进行解析,并显示到界面上。

Qt 中还提供了 FTP、DNS、SSL 等网络相关的组件工具,这里不做过多介绍。


2. Qt 音视频

2.1 Qt 音频

        在 Qt 中,音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只⽀持播放 wav 格式的音频文件。也就是说如果想要添加音频效果,那么首先需要将非 wav 格式的音频文件转换为 wav 格式。

通过帮助手册查看 QSound 类如下:

注意:使用 QSound 类时,需要添加模块: multimedia 。


(1)核心 API 概览


(2)示例


2.2 Qt 视频

        在 Qt 中,视频播放的功能主要是通过 QMediaPlayer 类和 QVideoWidget 类来实现。在使用这两个类时要添加对应的模块 multimedia 和 multimediawidgets。

(1)核心 API 概览


(2)示例

首先在 .pro 文件中添加 multimedia 和 multimediawidgets 两个模块。

如下图示:

widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QHBoxLayout>  //⽔平布局
#include <QVBoxLayout>  //垂直布局
#include <QVideoWidget> //显⽰视频
#include <QMediaPlayer> //播放声⾳
#include <QPushButton>  //按钮
#include <QStyle>       //设置图标
#include <QFileDialog>  //选择⽂件/⽂件夹class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void chooseVideo();private:QMediaPlayer *mediaPlayer;QVideoWidget *videoWidget;QVBoxLayout *vbox;//创建两个按钮:选择视频按钮和开播放按钮QPushButton *chooseBtn,*playBtn;};
#endif // WIDGET_H

widget.cpp :

#include "widget.h"
#include <QMediaPlayer>
#include <QSlider>Widget::Widget(QWidget *parent): QWidget(parent)
{//对象实例化mediaPlayer = new QMediaPlayer(this);videoWidget = new QVideoWidget(this);//设置播放画⾯的窗⼝videoWidget->setMinimumSize(600,600);//实例化窗⼝布局---垂直布局this->vbox = new QVBoxLayout(this);this->setLayout(this->vbox);//实例化选择视频按钮chooseBtn = new QPushButton("选择视频", this);//实例化播放按钮playBtn = new QPushButton(this);//设置图标代替⽂件playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));//实例化⼀个⽔平布局,将以上控件放⼊⽔平布局中QHBoxLayout *hbox = new QHBoxLayout;//添加控件hbox->addWidget(chooseBtn);hbox->addWidget(playBtn);//将播放窗⼝和⽔平布局都添加到垂直布局中vbox->addWidget(videoWidget);//布局中添加布局vbox->addLayout(hbox);//将选择视频对应的按钮和槽函数进⾏关联connect(chooseBtn,&QPushButton::clicked, this, &Widget::chooseVideo);
}void Widget::chooseVideo()
{//选择视频,返回⼀个播放视频的名字QString name = QFileDialog::getSaveFileName(this, "选择视频", ".", "WMV(*.wmv)");//设置媒体声⾳mediaPlayer->setMedia(QUrl(name));//输出视频画⾯mediaPlayer->setVideoOutput(videoWidget);//播放mediaPlayer->play();
}Widget::~Widget()
{}

本篇完。

下一篇是Qt开发⑫Qt界面优化之CSS。

相关文章:

Qt开发⑪Qt网络+Qt音视频_使用实操

目录 1. Qt 网络 1.1 UDP Socket 1.2 TCP Socket 1.3 HTTP Client 2. Qt 音视频 2.1 Qt 音频 2.2 Qt 视频 本篇完。 1. Qt 网络 和多线程类似&#xff0c;Qt 为了支持跨平台, 对网络编程的 API 也进行了重新封装。 实际 Qt 开发中进行网络编程&#xff0c;也不一定使用…...

JavaEE--计算机是如何工作的

一、一台计算机的组成部分 1.CPU&#xff08;中央处理器&#xff09; 2.主板&#xff08;一个大插座&#xff09; 3.内存&#xff08;存储数据的主要模板&#xff09; 4.硬盘&#xff08;存储数据的主要模板&#xff09; 内存和硬盘对比&#xff1a; 内存硬盘读写速度快慢存…...

API接口:企业名称、注册号、统一社会信用代码、企业类型、成立日期和法定代表人等数据 API 接口使用指南

API接口&#xff1a;企业名称、注册号、统一社会信用代码、企业类型、成立日期和法定代表人等数据 API 接口使用指南 本文详细介绍一种基于 Web 搜索方式实现的企业信息查询接口&#xff0c;适用于数据补全、企业资质验证、信息查询等场景。文章内容涵盖接口功能、请求参数、返…...

微信小程序text组件decode属性的小问题

今天学习微信小程序的text组件&#xff0c;这个组件类似于网页制作中的span标签&#xff0c;内联文本只能用 text 组件&#xff0c;不能用 view&#xff0c;如 foo bar </text。 text组件常用属性如下表&#xff1a; 属性说明user-select文本是否可选&#xff0c;该属性会使…...

【计算机网络入门】初学计算机网络(九)

目录 1.令牌传递协议 2. 局域网&IEEE802 2.1 局域网基本概念和体系结构 3. 以太网&IEEE802.3 3.1 MAC层标准 3.1.1 以太网V2标准 ​编辑 3.2 单播广播 3.3 冲突域广播域 4. 虚拟局域网VLAN 1.令牌传递协议 先回顾一下令牌环网技术&#xff0c;多个主机形成…...

LeetCode 974:和可被 K 整除的子数组

974. 和可被 K 整除的子数组 - 力扣&#xff08;LeetCode&#xff09; 给定一个整数数组 nums 和一个整数 k &#xff0c;返回其中元素之和可被 k 整除的非空 子数组 的数目。 子数组 是数组中 连续 的部分。 示例 1&#xff1a; 输入&#xff1a;nums [4,5,0,-2,-3,1], k …...

vector习题

完数和盈数 题目 完数VS盈数_牛客题霸_牛客网 一个数如果恰好等于它的各因子(该数本身除外)之和&#xff0c;如&#xff1a;6321。则称其为“完数”&#xff1b;若因子之和大于该数&#xff0c;则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。 输入描述&#xff…...

001-码云操作

码云操作 一、配置公钥1.官网地址1.进入 git bash2.查看生成的公钥3.设置到 Gitee4.测试 二、初始化一个项目1.新建仓库 一、配置公钥 方便后续提交代码不用填写密码 1.官网地址 官网地址&#xff1a;https://gitee.com/Git码云教程&#xff1a;https://gitee.com/help/arti…...

数据结构:二叉搜索树(排序树)

1.二叉搜索树的定义 二叉搜索树要么是空树&#xff0c;要么是满足以下特性的树 &#xff08;1&#xff09;左子树不为空&#xff0c;那么左子树左右节点的值都小于根节点的值 &#xff08;2&#xff09;右子树不为空&#xff0c;那么右子树左右节点的值都大于根节点的值 &#…...

【愚公系列】《Python网络爬虫从入门到精通》036-DataFrame日期数据处理

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

C++(蓝桥杯常考点)

前言&#xff1a;这个是针对于蓝桥杯竞赛常考的C内容&#xff0c;容器这些等下棋期再讲 C 在DEVC中注释和取消注释的方法&#xff1a;ctrl/ ASCII值&#xff08;常用的&#xff09;&#xff1a; A-Z:65-90 a-z:97-122 0-9:48-57 换行/n:10科学计数法&#xff1a;eg&#xff1a…...

支付宝 IoT 设备入门宝典(下)设备经营篇

上篇介绍了支付宝 IoT 设备管理&#xff0c;但除了这些基础功能外&#xff0c;商户还可以利用设备进行一些运营动作&#xff0c;让设备更好的帮助自己&#xff0c;本篇就会以设备经营为中心&#xff0c;介绍常见的设备相关能力和问题解决方案。如果对上篇感兴趣&#xff0c;可以…...

蓝桥杯 之 填空题-位运算与循环

文章目录 循环握手问题门牌制作-循环小球反弹幸运数艺术与篮球跑步卡片 位运算3个1美丽的2024 位运算 可以关注这个Lowbit(x) 如何判断最低位是否是1&#xff1f; num&1 1就说明num最低位是1 循环 循环 握手问题 握手问题 思路分析&#xff1a; 可以直接计算出来&…...

iOS逆向工程概述与学习路线图

iOS逆向工程概述与学习路线图 欢迎各位加入我的iOS逆向工程专栏&#xff01;在这个系列的第一篇文章中&#xff0c;我将为大家介绍iOS逆向工程的基本概念、应用场景以及完整的学习路线图&#xff0c;帮助大家建立清晰的学习框架。 什么是iOS逆向工程&#xff1f; 逆向工程&a…...

DeepSeek 助力 Vue3 开发:打造丝滑的时间选择器(Time Picker)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的时间选择器(Time Picker)📚前言📚页面效果📚指令输入…...

基于 Ingress-Nginx 实现 mTLS 双向认证

目录 背景描述&#xff1a; TLS 和 MTLS 之间的差异 通过自签名证书启用双向 TLS 1. 生成证书 (1) 生成 CA&#xff08;根证书颁发机构&#xff09; (2) 生成 CA&#xff08;根证书颁发机构&#xff09; (3) 生成客户端证书 2. 在 Kubernetes 中配置 mTLS &#x…...

学到什么记什么(25.3.3)

Upload-labs 今日重新做了一下文件上传漏洞&#xff0c;这里第一题之前采用直接抓包改后缀名.jpg为.php&#xff0c;再写入一句话<?php phpinfo();?>然后放行&#xff0c;得到图片地址&#xff08;可复制&#xff09;&#xff0c;本来直接访问图片地址即可得到敏感信息…...

【子网掩码计算器:Python + Tkinter 实现】

子网掩码计算器&#xff1a;Python Tkinter 实现 引言代码功能概述代码实现思路1. 界面设计2. 功能实现3. 事件处理 子网掩码计算器实现步骤1. 导入必要的库2. 定义主窗口类 SubnetCalculatorApp3. 创建菜单栏4. 创建界面组件5. 判断 IP 地址类别6. 计算子网信息7. 其他功能函…...

《解锁HarmonyOS NEXT高阶玩法:艺术图像识别功能开发全攻略》

在当今数字化时代&#xff0c;AI技术不断拓展其应用边界&#xff0c;为各行业带来前所未有的变革。在艺术领域&#xff0c;AI图像识别技术能够帮助艺术从业者、爱好者快速识别艺术品风格、作者&#xff0c;甚至挖掘艺术品背后的历史文化信息。本文将结合HarmonyOS NEXT API 12及…...

Spring Boot的启动流程

Spring Boot 的启动流程是一个复杂且有序的过程&#xff1a; 创建SpringApplication实例 — 调用run方法 — 启动完成(发布应用启动事件&#xff0c;配置环境&#xff0c;创建ApplicationContext&#xff0c;准备ApplicationContext&#xff0c;刷新ApplicationContext[【创建B…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...

深度解析云存储:概念、架构与应用实践

在数据爆炸式增长的时代&#xff0c;传统本地存储因容量限制、管理复杂等问题&#xff0c;已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性&#xff0c;成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理&#xff0c;云存储正重塑数据存储与…...

python基础语法Ⅰ

python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器&#xff0c;来进行一些算术…...