目录
[4.1 音频](#4.1 音频)
[4.2 视频](#4.2 视频)
文件操作是应用程序必不可少的部分。Qt作为一个通用开发库,提供了跨平台的文件操作能力。Qt提供了很多关于文件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件复制或重命名等
一、输入输出设备类
在Qt中,文件读写的类为QFile。QFile的父类为QFileDevice,QFileDevice提供了文件交互操作的底层功能。QFileDevice的父类是QIODevice,QIODevice的父类为QObject
QIODevice是Qt中所有输入输出设备(input/output device,简称 I/O 设备)的基础类,I/O 设备就是能进行数据输入和输出的设备,例如文件是一种 I/O 设备,网络通信中的 socket 是 I/O 设备,串口、蓝牙等通信接口也是 I/O 设备,它们也是从 QIODevice 继承来的
Qt中主要的一些 I/O 设备类的继承关系如下图所示:
- QFile是用于文件操作和文件数据读写的类,使用 QFile 可以读写任意格式的文件
- QSaveFile是用于安全保存文件的类。使用 QSaveFile 保存文件时,会先把数据写入一个临时文件,成功提交后才将数据写入最终的文件。若保存过程中出现错误,临时文件里的数据不会被写入最终文件,这样就能确保最终文件中不会丢失数据或被写入部分数据。在保存较大的文件或复杂格式的文件时可以使用该类,如从网络上下载文件等
- QTemporaryFile 是用于创建临时文件的类。使用函数 QTemporaryFile::open() 就能创建一个文件名唯一的临时文件,在 QTemporaryFile 对象被删除时,临时文件被自动删除
- QTcpSocket 和 QUdpSocket 是分别实现了 TCP 和 UDP 的类
- QSerialPort 是实现了串口通信的类,通过这个类可以实现计算机与串口设备的通信
- QBluetoothSocket是用于蓝牙通信的类。手机和平板计算机等移动设备有蓝牙通信模块,笔记本电脑一般也有蓝牙通信模块。通过QBluetoothSocket类,就可以编写蓝牙通信程序。如编程实现笔记本电脑与手机的蓝牙通信
- QProcess类用于启动外部程序,并且可以给程序传递参数
- QBuffer以一个QByteArray对象作为数据缓冲区,将QByteArray对象当作一个I/O设备来读写
二、文件读写类
在Qt中,文件的读写主要是通过QFile类来实现。在QFile类中提供了一些用来读写文件的方法
对于文件的操作主要有:
- 读数据:QFile类中提供了多个方法用于读取文件内容;如read()、readAll()、readLine()等
- 写数据:QFile类中提供了多个方法用于往文件中写内容;如write()、writeData()等
- 关闭文件:文件使用结束后必须用函数close()关闭文件
访问一个设备前,需要使用open()函数打开该设备,而且必须指定正确的打开模式,QIODevice中所有的打开模式由QIODevice::OpenMode枚举变量定义,其取值如下:
|-----------------------|----------------------------------------------------------|
| QIODevice::NotOpen | 没有打开设备 |
| QIODevice::ReadOnly | 以只读方式打开设备 |
| QIODevice::WriteOnly | 以只写方式打开设备 |
| QIODevice::ReadWrite | 以读写方式打开设备 |
| QIODevice::Append | 以追加方式打开设备,将数据写到文件末尾 |
| QIODevice::Truncate | 每次打开文件后重写文件内容,原内容将被删除 |
| QIODevice::Text | 读文件时,行尾终止符会转换为'\n' 写文件时,行尾终止符会被转换为本地编码。如Win32上为'\r\n' |
| QIODevice::Unbuffered | 无缓冲形式打开文件,绕过设备中的任何缓冲区 |
| QIODevice::NewOnly | 文件存在则打开失败,不存在则创建文件 |
**代码示例:**简易记事本
mainwindow.h
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenuBar>
#include <QPlainTextEdit>
#include <QFileDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void handleAction1();
void handleAction2();
private:
Ui::MainWindow *ui;
QPlainTextEdit* edit;
};
#endif // MAINWINDOW_H
mainwindow.cpp
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("简易记事本");
resize(1200, 1000);
QMenuBar* menubar = menuBar();
setMenuBar(menubar);
QMenu* menu1 = new QMenu("文件");
QMenu* menu2 = new QMenu("编辑");
QMenu* menu3 = new QMenu("查看");
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);
QAction* action1 = new QAction("打开");
QAction* action2 = new QAction("保存");
menu1->addAction(action1);
menu1->addAction(action2);
QFont font;
font.setPixelSize(25);
edit = new QPlainTextEdit();
edit->setFont(font);
setCentralWidget(edit);
connect(action1, &QAction::triggered, this, &MainWindow::handleAction1);
connect(action2, &QAction::triggered, this, &MainWindow::handleAction2);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleAction1()
{
//弹出打开文件的对话框
QString path = QFileDialog::getOpenFileName();
//将文件路径显示到状态栏
QStatusBar* statusbar = statusBar();
statusbar->showMessage(path);
//构造QFile对象,打开文件
QFile file(path);
bool ret = file.open(QIODevice::ReadOnly);
if(!ret) statusbar->showMessage(path + "打开失败");
//读取文件
QString text = file.readAll();
//关闭文件
file.close();
//将读取的内容设置到文本框中
edit->setPlainText(text);
}
void MainWindow::handleAction2()
{
//弹出保存文件的对话框
QString path = QFileDialog::getSaveFileName();
//将文件路径显示到状态栏
QStatusBar* statusbar = statusBar();
statusbar->showMessage(path);
//构造QFile对象,打开文件
QFile file(path);
bool ret = file.open(QIODevice::WriteOnly);
if(!ret) statusbar->showMessage(path + "打开失败");
//写文件
const QString& text = edit->toPlainText();
file.write(text.toUtf8());
//关闭文件
file.close();
}
三、文件和目录信息类
QFileInfo是Qt提供的一个用于获取文件和目录信息的类,如获取文件名、文件大小、文件修改日期等。QFileInfo类中提供了很多的方法,常用的有:
- isDir() 检查该文件是否是目录
- isExecutable() 检查该文件是否是可执行文件
- fileName() 获得文件名
- completeBaseName() 获取完整的文件名
- suffix() 获取文件后缀名
- completeSuffix() 获取完整的文件后缀
- size() 获取文件大小
- isFile() 判断是否为文件
- fileTime() 获取文件创建时间、修改时间、最近访问时间等
**代码示例:**查看文件信息
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QFileInfo>
#include <QFileDialog>
#include <QDateTime>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* button = new QPushButton("按钮", this);
connect(button, &QPushButton::clicked, [=]() {
QString path = QFileDialog::getOpenFileName(this, "查看文件信息", "./");
QFileInfo fileinfo(path);
//文件名
qDebug() << "文件名为:" << fileinfo.fileName().toUtf8().data();
//文件后缀名
qDebug() << "后缀名为:" << fileinfo.suffix().toUtf8().data();
//文件大小
qDebug() << "文件大小为:" << fileinfo.size();
//文件路径
qDebug() << "文件路径为:" << fileinfo.path().toUtf8().data();
//判断是否为⽂件
qDebug() << "是否为文件:"<< fileinfo.isFile();
//文件创建时间
QDateTime time1 = fileinfo.fileTime(QFileDevice::FileBirthTime);
qDebug() << "创建时间为:" << time1.toString("yyyy-MM-dd hh:mm:ss").toUtf8().data();
//文件的最后修改⽇期
QDateTime time2 = fileinfo.lastModified();
qDebug() << "最后修改时间为:"<< time2.toString("yyyy-MM-dd hh:mm:ss").toUtf8().data();
//判断是否为文件夹
qDebug() << "是否为目录:" << fileinfo.isDir();
});
}
Widget::~Widget()
{
delete ui;
}
四、音视频
4.1 音频
在 Qt 中,音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只支持播放 wav 格式的音频文件。即想要添加音频效果,先需要将非 wav 格式的音频文件转换为 wav 格式
**注意:**使用 QSound 类时,需要添加模块multimedia
**核心API:**play() 开始或继续播放当前源
代码示例
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QSound>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QSound* sound = new QSound(":/BackButtonSound.wav", this);
connect(ui->pushButton, &QPushButton::clicked, this, [=]() {
sound->play();
});
}
Widget::~Widget()
{
delete ui;
}
4.2 视频
在 Qt 中,视频播放的功能主要是通过 QMediaPlayer类 和 QVideoWidget类 来实现。在使用这两个类时要添加对应的模块 multimedia 和 multimediawidgets
代码示例
widget.h
cpp
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QHBoxLayout> //⽔平布局
#include <QVBoxLayout> //垂直布局
#include <QVideoWidget> //显⽰视频
#include <QMediaPlayer> //播放声⾳
#include <QPushButton> //按钮
#include <QStyle> //设置图标
#include <QFileDialog> //选择⽂件/⽂件夹
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void chooseVideo();
private:
Ui::Widget *ui;
QMediaPlayer *mediaPlayer;
QVideoWidget *videoWidget;
QVBoxLayout *vbox;
QPushButton *chooseBtn,*playBtn;
};
#endif // WIDGET_H
widget.cpp
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//对象实例化
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);
}
Widget::~Widget()
{
delete ui;
}
void Widget::chooseVideo()
{
//选择视频,返回⼀个播放视频的名字
QString name = QFileDialog::getSaveFileName(this, "选择视频", ".", "MP4(*.mp4)");
//设置媒体源
mediaPlayer->setMedia(QUrl(name));
//将视频输出附加到媒体播放器上
mediaPlayer->setVideoOutput(videoWidget);
//播放
mediaPlayer->play();
}