seo网站推广 杭州,微信营销神器,网站建设 logo,石家庄网站制作系统文章目录 1. 文件操作1.1 API1.2 例子1#xff0c;简单记事本1.3 例子2#xff0c;输出文件的属性 2. Qt 多线程2.1 常用API2.2 例子1#xff0c;自定义定时器 3. 线程安全3.1 互斥锁3.2 条件变量 4. 网络编程4.1 UDP Socket4.2 UDP Server4.3 UDP Client4.4 TCP Socket4.5 … 文章目录 1. 文件操作1.1 API1.2 例子1简单记事本1.3 例子2输出文件的属性 2. Qt 多线程2.1 常用API2.2 例子1自定义定时器 3. 线程安全3.1 互斥锁3.2 条件变量 4. 网络编程4.1 UDP Socket4.2 UDP Server4.3 UDP Client4.4 TCP Socket4.5 TCP Server4.6 TCP Client4.7 HTTP API4.8 HTTP Client 5. 播放音频 1. 文件操作
继承关系图如下 1.1 API
简单介绍一下文件操作的方法 QFile构造QFile::QFile(const QString name)通过给定的路径构造 打开文件使用 [override virtual] bool QFile::open(QIODeviceBase::OpenMode mode) 方法来打开文件。文件可以是文本文件或二进制文件。 QIODevice::ReadOnly以只读模式打开文件。QIODevice::WriteOnly以只写模式打开文件。QIODevice::ReadWrite以读写模式打开文件。 读取文件QByteArray QIODevice::readAll()来读取所有的文件内容 编写文件qint64 QIODevice::write(const QByteArray data)向文件写内容 关闭文件[virtual] void QIODevice::close()来关闭文件
1.2 例子1简单记事本
下面是一个例子实现了记事本的两个功能
#include mainwindow.h
#include QFile
#include QFileDialog
#include ui_mainwindow.hMainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui-setupUi(this);this-setWindowTitle(记事本Demo);// 添加菜单栏QMenuBar* menuBar this-menuBar();// 添加菜单QMenu* menu new QMenu(文件);menuBar-addMenu(menu);// 添加菜单项QAction* action_read new QAction(读取);QAction* action_save new QAction(保存);menu-addAction(action_read);menu-addAction(action_save);// 设置文本输入框edit new QPlainTextEdit(this);QFont font;font.setPixelSize(18);edit-setFont(font); // 设置字体大小this-setCentralWidget(edit);// 设置槽函数this-connect(action_read, QAction::triggered, this, MainWindow::handle_read_file);this-connect(action_save, QAction::triggered, this, MainWindow::handle_save_file);
}void MainWindow::handle_save_file()
{// 通过对话打开文件QString path QFileDialog::getSaveFileName(this, 保存文件);// 构建QFile对象QFile file QFile(path);// 打开文件bool ret file.open(QIODevice::WriteOnly);if (!ret) {qDebug() handle_save_file, 打开文件失败!;return;}// 向文件中写数据QString text edit-toPlainText();file.write(text.toUtf8());// 显示到状态栏中QStatusBar* statusBar this-statusBar();statusBar-showMessage(path QString( 写入成功!), 10000);// 关闭文件file.close();
}void MainWindow::handle_read_file()
{QString path QFileDialog::getOpenFileName(this, 读取文件);QFile file QFile(path);bool ret file.open(QIODevice::ReadOnly);if (!ret) {qDebug() handle_read_file, 打开文件失败!;return;}// QByteArray可以转换成QStringQString text file.readAll();edit-setPlainText(text);QStatusBar* statusBar this-statusBar();statusBar-showMessage(path QString( 读取成功!), 10000);file.close();
}MainWindow::~MainWindow()
{delete ui;
}1.3 例子2输出文件的属性
使用QFileInfo 该类用于获取文件或目录的详细信息例如文件路径、大小、创建时间、修改时间等。下面是一个例子
void Widget::on_pushButton_clicked()
{QString path QFileDialog::getOpenFileName(this);QFileInfo info(path);qDebug() File path: info.filePath();qDebug() File name: info.fileName();qDebug() Base name: info.baseName();qDebug() Suffix: info.suffix();qDebug() Size: info.size() bytes;qDebug() Exists: info.exists();qDebug() Is file: info.isFile();qDebug() Is directory: info.isDir();qDebug() Last modified: info.lastModified().toString(yyyy/MM/dd hh:mm:ss);
}运行结果如下 2. Qt 多线程
使用QThread类
2.1 常用API
API接口描述run()线程的入口函数。开发者需要重写此函数来定义线程执行的任务。start()通过调用 run() 函数开始执行线程。操作系统将根据优先级参数调度线程。如果线程已经在运行则此方法不执行任何操作。currentThread()返回一个指向管理当前执行线程的 QThread 的指针。isRunning()如果线程正在运行则返回 true否则返回 false。sleep() / msleep() / usleep()使线程休眠单位分别为秒、毫秒、微秒。这些函数允许线程暂停执行指定的时间。wait()阻塞调用它的线程直到与此 QThread 对象关联的线程完成执行即从 run() 返回或者等待时间已过如果指定了等待时间。如果线程已完成或尚未启动则返回 true如果等待超时则返回 false。terminate()尝试立即终止线程的执行。但请注意由于操作系统的调度策略线程可能不会立即终止。在调用 terminate() 后应使用 QThread::wait() 来确保线程已真正停止。然而通常不推荐使用 terminate()因为它可能会导致资源泄露或其他不可预知的行为。finished()当线程结束时会发出此信号。可以通过连接此信号来执行清理工作或其他必要的操作。isFinished() const判断线程中的任务是否处理完毕。priority() const得到当前线程的优先级。setPriority(Priority priority)设置线程的优先级。exit(int returnCode 0)退出线程停止底层的事件循环。quit()退出线程的事件循环与调用 exit() 效果相同。
创建线程的步骤
自定义一个类继承于 QThread并且只有一个线程处理函数(和主线程不是同一个线程)这个线程处理函数主要就是重写父类中的run()函数。线程处理函数里面写入需要执行的复杂数据处理启动线程不能直接调用 run()函数需要使用对象来调用 start()函数实现线程启动线程处理函数执行结束后可以定义一个信号来告诉主线程最后关闭线程
2.2 例子1自定义定时器
不使用QTimer实现定时效果首先定义一个Thread类继承自QThread
/* thread.h */
#ifndef THREAD_H
#define THREAD_H#include QThread
#include QWidgetclass Thread : public QThread
{Q_OBJECT
public:Thread();virtual void run();
signals:void timeout(); // 自定义信号每1s发送1次, 一共发送10次
};#endif // THREAD_H/* thread.cpp */
#include thread.hThread::Thread()
{
}void Thread::run()
{for (int i 1; i 10; i) {sleep(1);emit timeout();}
}在widget.ui中拖入一个QLcdNumber下面是Widget类的代码
/* widget.h */
#ifndef WIDGET_H
#define WIDGET_H#include QWidget
#include thread.hQT_BEGIN_NAMESPACE
namespace Ui
{
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget* parent nullptr);void handlerTime();~Widget();
private:Ui::Widget* ui;Thread timer;
};
#endif // WIDGET_H/* widget.cpp */
#include widget.h
#include ui_widget.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);ui-lcdNumber-display(10);connect(timer, Thread::timeout, this, Widget::handlerTime); // 连接信号槽timer.start(); // 启动该线程
}void Widget::handlerTime()
{int val ui-lcdNumber-intValue();ui-lcdNumber-display(--val);
}Widget::~Widget()
{delete ui;
}3. 线程安全
3.1 互斥锁
使用QMutex下面是一个例子 不加互斥锁让两个线程同一个变量
/* thread.h */
#ifndef THREAD_H
#define THREAD_H#include QThread
#include QWidgetclass Thread : public QThread
{Q_OBJECT
public:Thread();virtual void run();static int num;
};#endif // THREAD_H/* thread.cpp */
#include thread.hint Thread::num 0;Thread::Thread()
{
}void Thread::run()
{for (int i 1; i 50000; i) {num;}
}在Widget中创建这两个线程widget.cpp如下
#include widget.h
#include ui_widget.h
#include thread.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);Thread t1, t2;t1.start();t2.start();// 等待t1, t2执行完t1.wait();t2.wait();qDebug() Thread::num;
}Widget::~Widget()
{delete ui;
}由于操作并不是原子的所以结果可能并不全是100000要想结果一致需要加互斥锁修改thread.cpp
#include thread.hint Thread::num 0;
QMutex Thread::mutex QMutex();Thread::Thread()
{
}void Thread::run()
{for (int i 1; i 50000; i) {mutex.lock();num;mutex.unlock();}
}这样结果就能稳定了 RAII风格的锁使用[explicit noexcept] QMutexLocker::QMutexLocker(Mutex *mutex)将thread.cpp中的代码改为
#include thread.hint Thread::num 0;
QMutex Thread::mutex QMutex();Thread::Thread()
{
}void Thread::run()
{for (int i 1; i 50000; i) {QMutexLocker locker(mutex);num;}
}仍能起到同样的效果
3.2 条件变量
使用QWaitCondition类下面是一个例子仅仅作为演示
/* thread.cpp */
#include thread.hQMutex Thread::mutex QMutex();
QWaitCondition Thread::condition QWaitCondition();
int Thread::_cnt 0;Thread::Thread(int num): _num(num) {};void Thread::run()
{qDebug() Thread- _num created done.;for (;;) {QMutexLocker locker(Thread::mutex);// 阻塞当前线程等待别的线程使用notify_one()或wakeAll()来唤醒它。condition.wait(mutex);_cnt;printf(Thread-%d, cnt: %d\n, _num, _cnt);condition.notify_one();}
}/* widget.cpp */
#include widget.h
#include Windows.h
#include thread.h
#include ui_widget.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);Thread t1(1);Thread t2(2);Thread t3(3);t1.start();t2.start();t3.start();QThread::msleep(1000);qDebug() Main thread start control.;for(;;) {QMutexLocker locker(Thread::mutex);Thread::condition.notify_one(); // 唤醒等待队列中等待的一个线程, 默认是第一个}
}Widget::~Widget()
{delete ui;
}运行后会发现线程以1,2,3的顺序一直在运行
4. 网络编程
4.1 UDP Socket
QUdpSocket表示一个UDP的socket文件
API 接口类型说明对标原生 APIbind(const QHostAddress, quint16)方法绑定指定的本地地址和端口号准备接收数据报bindreceiveDatagram()方法接收一个 UDP 数据报并返回 QNetworkDatagram 对象包含数据报的内容和发送方信息recvfromwriteDatagram(const QNetworkDatagram)方法发送一个 UDP 数据报包含目标地址和端口号sendtoreadyRead信号当有新的数据报到达并准备好读取时触发通知应用程序可以读取数据无类似于 I/O 多路复用的通知机制
QNetworkDatagram表示一个UDP数据报
方法/构造函数类型说明对标原生 APIQNetworkDatagram(const QByteArray, const QHostAddress ip, quint16 port)构造函数通过 QByteArray 数据、目标 IP 地址和目标端口号构造一个 UDP 数据报。通常用于发送数据时封装数据报内容。无data()方法获取数据报内部持有的数据返回 QByteArray 类型包含数据报的原始字节数据。无在网络编程中原生 API 通常通过读取缓冲区获得数据senderAddress()方法获取数据报中包含的对端的 IP 地址返回 QHostAddress表示发送该数据报的远端主机地址。无但在原生 UDP 编程中recvfrom 函数包含了获取发送方地址的功能。senderPort()方法获取数据报中包含的对端的端口号返回 quint16 类型表示发送该数据报的远端主机的端口号。无但在原生 UDP 编程中recvfrom 函数包含了获取发送方端口号的功能。
4.2 UDP Server
下面是一个UDP回显服务器
首先要在.pro文件中加上network模块
QT core gui network在widget.ui中铺上一个QListWidget
下面是widget.h的代码
#ifndef WIDGET_H
#define WIDGET_H#include QWidget
#include QUdpSocketQT_BEGIN_NAMESPACE
namespace Ui
{
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget* parent nullptr);void handlerRequest();QString resolutionRequest(const QString request);~Widget();private:QUdpSocket* socket;Ui::Widget* ui;
};
#endif // WIDGET_H下面是wigdet.cpp的代码
#include widget.h
#include QMessageBox
#include QNetworkDatagram
#include ui_widget.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);socket new QUdpSocket(this);this-setWindowTitle(服务端);// 连接信号槽用于处理来自客户端的请求this-connect(socket, QUdpSocket::readyRead, this, Widget::handlerRequest);// 绑定端口号和IP(该套接字将会监听所有本地网络接口)bool ret socket-bind(QHostAddress::Any, 9000);if (!ret) {QMessageBox::critical(this, 绑定出错!, socket-errorString());return;}qDebug() 绑定端口和IP成功;
}void Widget::handlerRequest()
{// 读取请求const QNetworkDatagram requestDatagram socket-receiveDatagram();QString requet requestDatagram.data();// 获取客户端的IP和端口号QHostAddress peerIp requestDatagram.senderAddress();qint16 peerPort requestDatagram.senderPort();// 解析请求, 得到响应QString response resolutionRequest(requet);// 构建数据包将数据发送给客户端QNetworkDatagram sendDatagram QNetworkDatagram(response.toUtf8(), peerIp, peerPort);socket-writeDatagram(sendDatagram);// 自己这里要显示数据QString log [ peerIp.toString() : QString::number(peerPort) ] request: requet response: response;ui-listWidget-addItem(log);
}QString Widget::resolutionRequest(const QString request)
{// 用于解析请求, 这里仅做简单的字符串处理(将字符串逆转)QString res;for (int i request.size() - 1; i 0; --i) {res request[i];}return res;
}Widget::~Widget()
{delete ui;
}4.3 UDP Client
在wiget.ui中设置基本框架 下面是widget.h的代码
#ifndef WIDGET_H
#define WIDGET_H#include QUdpSocket
#include QWidgetQT_BEGIN_NAMESPACE
namespace Ui
{
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget* parent nullptr);void handlerResponse();~Widget();private slots:void on_pushButton_clicked();private:const static QHostAddress SERVER_IP;const static qint16 SERVER_PORT;QUdpSocket* socket;Ui::Widget* ui;
};
#endif // WIDGET_H下面是widget.cpp的代码
#include widget.h
#include QNetworkDatagram
#include QShortcut
#include ui_widget.hconst QHostAddress Widget::SERVER_IP QHostAddress(127.0.0.1);
const qint16 Widget::SERVER_PORT 9000;Widget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);socket new QUdpSocket(this);this-setWindowTitle(客户端);this-connect(ui-lineEdit, QLineEdit::editingFinished, this, Widget::on_pushButton_clicked); // 按回车发送this-connect(socket, QUdpSocket::readyRead, this, Widget::handlerResponse);qDebug() 连接服务端成功!;
}void Widget::handlerResponse()
{QNetworkDatagram responseDatagram socket-receiveDatagram(); // 接受数据报ui-listWidget-addItem(QString(Server say: ) responseDatagram.data()); // 显示
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{const QString text ui-lineEdit-text();if (text ) {qDebug() LineEdit Empty;return;}QNetworkDatagram requestDatagram(text.toUtf8(), SERVER_IP, SERVER_PORT); // 构建数据报socket-writeDatagram(requestDatagram); // 发送数据报ui-listWidget-addItem(QString(Client say: ) text); // 显示ui-lineEdit-setText(); // 清空
}同时运行客户端与服务端结果如下 4.4 TCP Socket
QTcpServer用于监听端口和获取客户端连接
名称类型说明对标原生 APIlisten(const QHostAddress, quint16 port)方法绑定指定的地址和端口号并开始监听。bind()和listen()nextPendingConnection()方法从系统中获取一个已经建立好的 TCP 连接。返回一个 QTcpSocket表示这个客户端的连接。通过这个 socket 对象完成和客户端之间的通信。accept()newConnection信号有新的客户端建立连接后触发。类似于 IO 多路复用中的通知机制。无但类似于 IO 多路复用中的通知机制
QTcpSocket用于客户端和服务器之间的数据交互
名称类型说明对标原生 APIreadAll()方法读取当前接收缓冲区中的所有数据。返回 QByteArray 对象。read()write(const QByteArray)方法把数据写入 socket 中。write()deleteLater方法把 socket 对象标记为无效。Qt 会在下个事件循环中析构释放该对象。无但类似于“半自动化的垃圾回收”readyRead信号有数据到达并准备就绪时触发。无但类似于 IO 多路复用中的通知机制disconnected信号连接断开时触发。无但类似于 IO 多路复用中的通知机制
4.5 TCP Server
下面是一个TCP回显服务器不要忘记在pro文件中加上network首先在wigdet.ui中添加一个QListWidget
wiget.h如下
#ifndef WIDGET_H
#define WIDGET_H#include QTcpSocket
#include QWidgetQT_BEGIN_NAMESPACE
namespace Ui
{
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget* parent nullptr);void handleResponse();~Widget();private slots:void on_pushButton_clicked();private:const static QHostAddress SERVER_IP;const static qint16 SERVER_PORT;Ui::Widget* ui;QTcpSocket* socket;
};
#endif // WIDGET_Hwidget.cpp
#include widget.h
#include QMessageBox
#include ui_widget.hconst QHostAddress Widget::SERVER_IP QHostAddress(127.0.0.1);
const qint16 Widget::SERVER_PORT 9000;Widget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);this-setWindowTitle(客户端);socket new QTcpSocket(this);socket-connectToHost(Widget::SERVER_IP, Widget::SERVER_PORT); // 连接客户端这是一个非阻塞的函数bool ret socket-waitForConnected(); // 等待连接服务器, 若ret为0表示三次握手成功if (!ret) {QMessageBox::critical(this, 等待连接失败, socket-errorString());return;}this-connect(ui-lineEdit, QLineEdit::editingFinished, this, Widget::handleResponse); // 按回车发送this-connect(socket, QTcpSocket::readyRead, this, Widget::handleResponse); // 设置信号槽, 当有数据来时执行
}void Widget::handleResponse()
{QString text socket-readAll(); // 读取ui-listWidget-addItem(QString(Server say: ) text); // 显示
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QString text ui-lineEdit-text();if (text ) {qDebug() Text empty!;return;}ui-listWidget-addItem(QString(Client say: ) text); // 显示socket-write(text.toUtf8()); // 写给客户端ui-lineEdit-setText(); // 清空
}4.6 TCP Client
widget.ui如下 wigdet.h
#ifndef WIDGET_H
#define WIDGET_H#include QTcpSocket
#include QWidgetQT_BEGIN_NAMESPACE
namespace Ui
{
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget* parent nullptr);void handleResponse();~Widget();private slots:void on_pushButton_clicked();private:const static QHostAddress SERVER_IP;const static qint16 SERVER_PORT;Ui::Widget* ui;QTcpSocket* socket;
};
#endif // WIDGET_Hwidget.cpp
#include widget.h
#include QMessageBox
#include ui_widget.hconst QHostAddress Widget::SERVER_IP QHostAddress(127.0.0.1);
const qint16 Widget::SERVER_PORT 9000;Widget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);this-setWindowTitle(客户端);socket new QTcpSocket(this);socket-connectToHost(Widget::SERVER_IP, Widget::SERVER_PORT); // 连接客户端这是一个非阻塞的函数bool ret socket-waitForConnected(); // 等待连接服务器, 若ret为0表示三次握手成功if (!ret) {QMessageBox::critical(this, 等待连接失败, socket-errorString());return;}this-connect(ui-lineEdit, QLineEdit::editingFinished, this, Widget::on_pushButton_clicked); // 按回车发送this-connect(socket, QTcpSocket::readyRead, this, Widget::handleResponse); // 设置信号槽, 当有数据来时执行
}void Widget::handleResponse()
{QString text socket-readAll(); // 读取ui-listWidget-addItem(QString(Server say: ) text); // 显示
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QString text ui-lineEdit-text();if (text ) {qDebug() Text empty!;return;}ui-listWidget-addItem(QString(Client say: ) text); // 显示socket-write(text.toUtf8()); // 写给客户端ui-lineEdit-setText(); // 清空
}运行结果如下 4.7 HTTP API
QNetworkAccessManager提供了HTTP的核心操作
方法说明get(const QNetworkRequest)发起一个 HTTP GET 请求。返回 QNetworkReply 对象。post(const QNetworkRequest, const QByteArray)发起一个 HTTP POST 请求。返回 QNetworkReply 对象。
QNetworkRequest表示一个HTTP请求不含body 如果需要发送一个带有 body 的请求比如 post会在 QNetworkAccessManager 的 post 方法中通过单独的参数来传入 body。 方法说明QNetworkRequest(const QUrl )通过 URL 构造一个 HTTP 请求。setHeader(QNetworkRequest::KnownHeaders header, const QVariant value)设置请求头。
QNetworkRequest::KnownHeaders是一个枚举请求下面是常用类型
取值说明ContentTypeHeader描述 body 的类型。ContentLengthHeader描述 body 的长度。LocationHeader用于重定向报文中指定重定向地址响应中使用请求用不到。CookieHeader设置 cookie。UserAgentHeader设置 User-Agent。
QNetworkReply表示一个HTTP响应
方法说明error()获取出错状态。errorString()获取出错原因的文本。readAll()读取响应 body。header(QNetworkRequest::KnownHeaders header)读取响应指定 header 的值。
QNetworkReply还有一个信号finished会在客户端收到完整的响应数据触发
在读取完后调用deleteLater()来释放该响应
4.8 HTTP Client
下面是一个简单的HTTP Client
在widget.ui中设置基本框架 widget.cpp如下
#include widget.h
#include QMessageBox
#include QNetworkReply
#include ui_widget.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);this-setWindowTitle(HTTP客户端);manager new QNetworkAccessManager(this);this-connect(ui-lineEdit, QLineEdit::editingFinished, this, Widget::on_pushButton_clicked);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QString text ui-lineEdit-text();if (text.isEmpty()) {qDebug() Text Empty!;QMessageBox::warning(this, 警告, 输入框中没有内容!);return;}// 构建请求QUrl url(text);QNetworkRequest request(url);// 发送请求QNetworkReply* response manager-get(request);if (response-error() QNetworkReply::NoError) {// 没有错误connect(response, QNetworkReply::finished, this, []() { // 当在客户端收到完整的响应数据触发qDebug() 读取到了数据;QString resultHtml response-readAll(); // 读取数据ui-extEdit-setPlainText(resultHtml);});} else {// 有错误QString errorStr response-errorString();qDebug() errorStr;QMessageBox::warning(this, 警告, errorStr);}
}运行结果如下 5. 播放音频
使用QSoundEffect类下面是一个例子
首先需要在pro文件中加上multimedia模块
widget.cpp如下
#include widget.h
#include error.h
#include QFile
#include ui_widget.hWidget::Widget(QWidget* parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);sound new QSoundEffect(this);// QString filePath D:/bit/QT/QTPro/25_2_24QSound_1/666.wav; // 使用正斜杠QString filePath :/sound/666.wav;if (!QFile::exists(filePath)) {qDebug() 音频文件不存在;return;}// 正确转换为QUrl必须使用QUrl使用QSting会加载失败const QUrl path QUrl::fromLocalFile(filePath);// const QUrl path QUrl(filePath); errsound-setSource(path);sound-setLoopCount(QSoundEffect::Infinite);connect(sound, QSoundEffect::statusChanged, this, [this]() {if (sound-status() QSoundEffect::Ready) {qDebug() 音频加载成功;} else if (sound-status() QSoundEffect::Error) {qDebug() 音频加载失败原因: 文件格式不支持或路径错误;}});
}
Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{sound-play();
}void Widget::on_pushButton_2_clicked()
{sound-stop();
}点击按钮1播放音频按钮2暂停音频 文章转载自: http://www.morning.fkflc.cn.gov.cn.fkflc.cn http://www.morning.xqwq.cn.gov.cn.xqwq.cn http://www.morning.eshixi.com.gov.cn.eshixi.com http://www.morning.snrhg.cn.gov.cn.snrhg.cn http://www.morning.mtqqx.cn.gov.cn.mtqqx.cn http://www.morning.yqsq.cn.gov.cn.yqsq.cn http://www.morning.wrlff.cn.gov.cn.wrlff.cn http://www.morning.pzlcd.cn.gov.cn.pzlcd.cn http://www.morning.kyctc.cn.gov.cn.kyctc.cn http://www.morning.srrrz.cn.gov.cn.srrrz.cn http://www.morning.pghry.cn.gov.cn.pghry.cn http://www.morning.ydflc.cn.gov.cn.ydflc.cn http://www.morning.lpbrp.cn.gov.cn.lpbrp.cn http://www.morning.ljglc.cn.gov.cn.ljglc.cn http://www.morning.wmgjq.cn.gov.cn.wmgjq.cn http://www.morning.kpnpd.cn.gov.cn.kpnpd.cn http://www.morning.ktqtf.cn.gov.cn.ktqtf.cn http://www.morning.gbhsz.cn.gov.cn.gbhsz.cn http://www.morning.rcww.cn.gov.cn.rcww.cn http://www.morning.yxwrr.cn.gov.cn.yxwrr.cn http://www.morning.cdlewan.com.gov.cn.cdlewan.com http://www.morning.hnhsym.cn.gov.cn.hnhsym.cn http://www.morning.npxht.cn.gov.cn.npxht.cn http://www.morning.ykwbx.cn.gov.cn.ykwbx.cn http://www.morning.trjdr.cn.gov.cn.trjdr.cn http://www.morning.ohmyjiu.com.gov.cn.ohmyjiu.com http://www.morning.liyixun.com.gov.cn.liyixun.com http://www.morning.yhpq.cn.gov.cn.yhpq.cn http://www.morning.jpdbj.cn.gov.cn.jpdbj.cn http://www.morning.jgnjl.cn.gov.cn.jgnjl.cn http://www.morning.ckntb.cn.gov.cn.ckntb.cn http://www.morning.crrjg.cn.gov.cn.crrjg.cn http://www.morning.srbl.cn.gov.cn.srbl.cn http://www.morning.kkysz.cn.gov.cn.kkysz.cn http://www.morning.wbfly.cn.gov.cn.wbfly.cn http://www.morning.brzlp.cn.gov.cn.brzlp.cn http://www.morning.kgjyy.cn.gov.cn.kgjyy.cn http://www.morning.qhjkz.cn.gov.cn.qhjkz.cn http://www.morning.aiai201.cn.gov.cn.aiai201.cn http://www.morning.jrhcp.cn.gov.cn.jrhcp.cn http://www.morning.cflxx.cn.gov.cn.cflxx.cn http://www.morning.pgkpt.cn.gov.cn.pgkpt.cn http://www.morning.wflsk.cn.gov.cn.wflsk.cn http://www.morning.skbhl.cn.gov.cn.skbhl.cn http://www.morning.fjlsfs.com.gov.cn.fjlsfs.com http://www.morning.jmwrj.cn.gov.cn.jmwrj.cn http://www.morning.phlrp.cn.gov.cn.phlrp.cn http://www.morning.hbkkc.cn.gov.cn.hbkkc.cn http://www.morning.zqkms.cn.gov.cn.zqkms.cn http://www.morning.rbsxf.cn.gov.cn.rbsxf.cn http://www.morning.fflnw.cn.gov.cn.fflnw.cn http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn http://www.morning.gkjnz.cn.gov.cn.gkjnz.cn http://www.morning.mgmqf.cn.gov.cn.mgmqf.cn http://www.morning.bqwsz.cn.gov.cn.bqwsz.cn http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn http://www.morning.hdscx.cn.gov.cn.hdscx.cn http://www.morning.hnhkz.cn.gov.cn.hnhkz.cn http://www.morning.zxfr.cn.gov.cn.zxfr.cn http://www.morning.lmrjn.cn.gov.cn.lmrjn.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.tmjhy.cn.gov.cn.tmjhy.cn http://www.morning.prls.cn.gov.cn.prls.cn http://www.morning.rkkpr.cn.gov.cn.rkkpr.cn http://www.morning.fcwb.cn.gov.cn.fcwb.cn http://www.morning.ymhzd.cn.gov.cn.ymhzd.cn http://www.morning.mplld.cn.gov.cn.mplld.cn http://www.morning.bnrff.cn.gov.cn.bnrff.cn http://www.morning.ggnjq.cn.gov.cn.ggnjq.cn http://www.morning.fbpyd.cn.gov.cn.fbpyd.cn http://www.morning.rhwty.cn.gov.cn.rhwty.cn http://www.morning.kcxtz.cn.gov.cn.kcxtz.cn http://www.morning.nrwr.cn.gov.cn.nrwr.cn http://www.morning.rsfp.cn.gov.cn.rsfp.cn http://www.morning.crsqs.cn.gov.cn.crsqs.cn http://www.morning.jjtwh.cn.gov.cn.jjtwh.cn http://www.morning.njddz.cn.gov.cn.njddz.cn http://www.morning.rbhcx.cn.gov.cn.rbhcx.cn http://www.morning.ggfdq.cn.gov.cn.ggfdq.cn http://www.morning.jrlgz.cn.gov.cn.jrlgz.cn