哈喽,我是老吴。
最近又玩了一下 Qt,给大家分享一点 Qt 相关的基础知识吧。
我个人非常喜欢 Qt,它简直就是我这个 C++ 手残党的利器。
学习 Qt 的最佳途径应该是阅读官方的手册和示例,今天要分享的就是 Qt 官方提供的一个示例。
http 下载小工具:
源码文件:
Makefile
httpwindow.cpp
main.cpp
httpwindow.h
http.pro
下面快速地说明一下如何实现这个小工具, let's go.
目录:
1. 实现主界面
2. 解析 URL 和创建空文件
3. 发送 http 请求和接收 http 数据
4. 添加进度条
5. 下载完成后自动打开文件
1. 实现主界面
主界面基于 QDialog,包括:
- 3 个 LineEdit;
- 1 个 CheckBox;
- 1 个 Label;
- 2 个 Button;
代码如下:
httpwindow.h
class HttpWindow : public QDialog
{
...
}
httpwindow.cpp
HttpWindow::HttpWindow(QWidget *parent)
: QDialog(parent)
...{
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(tr("&URL:"), urlLineEdit);
formLayout->addRow(tr("&Download directory:"), downloadDirectoryLineEdit);
formLayout->addRow(tr("Default &file:"), defaultFileLineEdit);
formLayout->addRow(launchCheckBox);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(formLayout);
mainLayout->addWidget(statusLabel);
QPushButton *quitButton = new QPushButton(tr("Quit"));
QWidget::close);
QDialogButtonBox *buttonBox = new QDialogButtonBox;
buttonBox->addButton(downloadButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
mainLayout->addWidget(buttonBox);
}
用 QFormLayout 对 3 个编辑框进行表单布局,然后再QVBoxLayout 来进行整体的垂直布局。
main.cpp:
int main(int argc, char *argv[]){
...
HttpWindow httpWin;
httpWin.show();
...
}
运行效果:
此时只有界面, Download 按键并没有实际的功能。
2. 解析 URL 和创建空文件
当用户点击 Downaload 按键时,需要解析用户输入的 URL 并打开一个新文件用于保存将要下载的文件。
代码如下:
1. 为 Download 按键绑定槽
connect(downloadButton, &QAbstractButton::clicked, this, &HttpWindow::downloadFile);
}
2. 解析 URL
void HttpWindow::downloadFile(){
// 获得 URL
const QString urlSpec = urlLineEdit->text().trimmed();
const QUrl newUrl = QUrl::fromUserInput(urlSpec);
// 获得 文件保存路径
QString fileName = newUrl.fileName();
QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
fileName.prepend(downloadDirectory + '/');
}
从 URL 中提取出文件名,和下载路径拼接在一起形成完整的文件路径。
3. 创建空文件
void HttpWindow::downloadFile(){
...
if (QFile::exists(fileName)) {
QFile::remove((fileName));
}
file = openFileForWrite(fileName);
...
}
std::unique_ptr HttpWindow::openFileForWrite(const QString &fileName) {
std::unique_ptr file(new QFile(fileName)) ;
file->open(QIODevice::WriteOnly);
return file;
}
运行效果:
3. 发送 http 请求和接收 http 数据
在 Qt 里,可以用 QNetworkAccessManager 发送 http request,用 QNetworkReply 保存 http reply。
class HttpWindow : public QDialog
{
private:
...
QUrl url;
QNetworkAccessManager qnam;
QNetworkReply *reply;
};
当用户按下 Download 键时,发送 http request:
void HttpWindow::startRequest(const QUrl &requestedUrl){
url = requestedUrl;
reply = qnam.get(QNetworkRequest(url));
connect(reply, &QIODevice::readyRead, this, &HttpWindow::httpReadyRead);
connect(reply, &QNetworkReply::finished, this, &HttpWindow::httpFinished);
statusLabel->setText(tr("Downloading %1...").arg(url.toString()));
}
当有数据到来时,将其写到文件中:
void HttpWindow::httpReadyRead(){
if (file)
file->write(reply->readAll());
}
当数据传输完毕后,提示用户下载完毕:
void HttpWindow::httpFinished(){
QFileInfo fi;
if (file) {
fi.setFile(file->fileName());
file->close();
file.reset();
}
statusLabel->setText(tr("Downloaded %1 bytes to %2\nin\n%3")
.arg(fi.size()).arg(fi.fileName(), QDir::toNativeSeparators(fi.absolutePath())));
downloadButton->setEnabled(true);
}
运行效果:
4. 添加进度条
发送请求后,创建一个进度条。
进度条的百分比和 http reply 的数据绑定在一起:
void HttpWindow::startRequest(const QUrl &requestedUrl){
...
ProgressDialog *progressDialog = new ProgressDialog(url, nullptr);
...
connect(reply, &QNetworkReply::downloadProgress, progressDialog, &ProgressDialog::networkReplyProgress);
...
progressDialog->show();
}
// 更新进度条的百分比
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes){
setMaximum(totalBytes);
setValue(bytesRead);
}
运行效果:
5. 下载完成后自动打开文件
QDesktopServices 用于访问常见的桌面服务。
许多桌面环境都会提供一系列服务,可以通过应用程序来执行常见任务。例如以用户应用程序首选项的方式打开一个网页或者 PDF。
当下载完毕后,如果用户使能了 Launch file 选项,则打开此下载文件:
void HttpWindow::httpFinished(){
...
if (launchCheckBox->isChecked()) {
QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));
}
downloadButton->setEnabled(true);
}
运行效果:
到此,这个 http 下载小工具就实现完毕啦。
嘿嘿,你们会学会了吗?
相关参考
https://doc.qt.io/qt-5/qtnetwork-http-example.html
思考技术,也思考人生
要学习技术,更要学习如何生活。
好书推荐:
《指数基金投资指南》
作者银行螺丝钉,专注于低估值指数基金投资,系统性地讲解各类指数基金,以及投资指数基金的有效策略。
能收获什么?
- 温习了一些关于基金定投的基础知识;
你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。
觉得文章对你有价值,不妨 在看 + 分享。
推荐阅读:
专辑 | Linux 驱动开发
专辑 | 每天一点 C
专辑 | Linux 系统编程