
一个基于Qt和百度翻译API的翻译小项目。本文将按文件简单说明代码和业务逻辑。
1.main.cpp —— 程序入口
//main.cpp
#include "translate.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Translate w;
w.show();
return a.exec();
}
创建 QApplication 对象,初始化 Qt 应用环境。创建主窗口 Translate,调用 show() 显示界面。返回a.exec() 进入事件循环。
2.translate.h —— 翻译主窗口类
//translate.h
#ifndef TRANLATE_H
#define TRANLATE_H
#include <QCloseEvent>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QPainter>
#include <QTextStream>
#include <Qwidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Translate;
}
QT_END_NAMESPACE
class Translate : public QWidget {
Q_OBJECT
public:
Translate(QWidget *parent = nullptr);
~Translate();
QNetworkAccessManager *manager;
void closeEvent(QCloseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private slots:
void on_pushButton_Translate_clicked();
void on_pushButton_Clear_clicked();
void ReplyFunc(QNetworkReply *);
private:
Ui::Translate *ui;
};
#endif // TRANLATE_H
继承自 QWidget的主界面窗口类。定义了翻译窗口的整体结构。
成员变量
QNetworkAccessManager *manager,用于发送网络请求。
重写函数
closeEvent():窗口关闭时的保存动作。
paintEvent():自定义背景绘制。
槽函数
on_pushButton_Translate_clicked():“翻译”按钮点击槽函数。
on_pushButton_Clear_clicked():“清空”按钮点击槽函数。
ReplyFunc(QNetworkReply *):网络响应槽函数。
3.translate.cpp —— 代码实现
//translate.cpp
#include "translate.h"
#include "ui_translate.h"
Translate::Translate(QWidget *parent) : QWidget(parent), ui(new Ui::Translate) {
ui->setupUi(this);
setFixedSize(this->width(), this->height());
this->setStyleSheet("background-color:#f0f0f0;");
// 设置下拉框样式
ui->comboBox_CE->setStyleSheet("QComboBox{"
"background-color:white;"
"border: 1px solid #ccc;"
"border-radius:5px;"
"padding:5px;"
"min-height:26px;"
"}"
"QComboBox::drop-down{"
"sub-control-origin:padding;"
"sub-control-position:right center;"
"width:20px;"
"border-left:1px solid #ccc;"
"}");
// 设置按钮样式
ui->pushButton_Translate->setStyleSheet("QPushButton}"
"background-color:#4acf50;"
"color:white;"
"border-radius:5px;"
"padding:10px;"
"min-height:15px;"
"}"
"QPushButton:hover{"
"background-color:#45a049;"
"}");
ui->pushButton_Clear->setStyleSheet("QPushButton}"
"background-color:#f44336;"
"color:white;"
"border-radius:5px;"
"padding:10px;"
"min-height:15px;"
"}"
"QPushButton:hover{"
"background-color:#d32f2f;"
"}");
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), this,
SLOT(ReplyFunc(QNetworkReply *)));
}
void Translate::paintEvent(QPaintEvent *event) {
Q_UNUSED(event);
QPainter painter(this);
QLinearGradient gradient(0, 0, width(), height());
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::blue);
painter.fillRect(rect(), gradient);
}
Translate::~Translate() { delete ui; }
void Translate::on_pushButton_Translate_clicked() {
QString inputText = ui->textEdit_InputText->toPlainText();
QString encodedText = QUrl::toPercentEncoding(inputText);
QString appid = "your_appid";
QString secretKey = "your_secretKey";
QString salt = QString::number(QDateTime::currentSecsSinceEpoch());
QString signRaw = appid + inputText + salt + secretKey;
QByteArray md5Hash =
QCryptographicHash::hash(signRaw.toUtf8(), QCryptographicHash::Md5);
QString sign = md5Hash.toHex();
QString toLang =
(ui->comboBox_CE->currentText() == "中文翻译英文") ? "en" : "zh";
QString apiUrl = QString("http://api.fanyi.baidu.com/api/trans/vip/translate"
"?q=%1&from=auto&to=%2&appid=%3&salt=%4&sign=%5")
.arg(encodedText)
.arg(toLang)
.arg(appid)
.arg(salt)
.arg(sign);
QNetworkRequest request;
request.setUrl(QUrl(apiUrl));
manager->get(request);
}
void Translate::on_pushButton_Clear_clicked() { ui->textEdit_Record->clear(); }
void Translate::closeEvent(QCloseEvent *event) {
QString strText = ui->textEdit_Record->toPlainText();
QFile file("logfile.txt");
if (file.open(QIODevice::Append | QIODevice::Text)) {
QTextStream out(&file);
out << strText << "\n";
file.close();
}
event->accept();
}
void Translate::ReplyFunc(QNetworkReply *reply) {
ui->textEdit_Result->clear();
QJsonParseError jsonError;
QJsonDocument json = QJsonDocument::fromJson(reply->readAll(), &jsonError);
if (jsonError.error == QJsonParseError::NoError && json.isObject()) {
QJsonObject rootjson = json.object();
if (rootjson.contains("trans_result")) {
QJsonValue resultValue = rootjson.value(QString("trans_result"));
QJsonArray array = resultValue.toArray();
QString strMean = "";
for (int i = 0; i < array.size(); i++) {
QJsonObject explains = array.at(i).toObject();
if (explains.contains("dst")) {
QJsonValue dst = explains.value(QString("dst"));
strMean += dst.toString();
}
}
ui->textEdit_Result->append(strMean);
}
}
ui->textEdit_Record->append(ui->textEdit_InputText->toPlainText() + "->" +
ui->textEdit_Result->toPlainText());
}
实现头文件中声明的业务逻辑。
Translate::Translate(QWidget *parent) : QWidget(parent), ui(new Ui::Translate) {
ui->setupUi(this);
setFixedSize(this->width(), this->height());
this->setStyleSheet("background-color:#f0f0f0;");
// 设置下拉框样式
ui->comboBox_CE->setStyleSheet("QComboBox{"
"background-color:white;"
"border: 1px solid #ccc;"
"border-radius:5px;"
"padding:5px;"
"min-height:26px;"
"}"
"QComboBox::drop-down{"
"sub-control-origin:padding;"
"sub-control-position:right center;"
"width:20px;"
"border-left:1px solid #ccc;"
"}");
// 设置按钮样式
ui->pushButton_Translate->setStyleSheet("QPushButton}"
"background-color:#4acf50;"
"color:white;"
"border-radius:5px;"
"padding:10px;"
"min-height:15px;"
"}"
"QPushButton:hover{"
"background-color:#45a049;"
"}");
ui->pushButton_Clear->setStyleSheet("QPushButton}"
"background-color:#f44336;"
"color:white;"
"border-radius:5px;"
"padding:10px;"
"min-height:15px;"
"}"
"QPushButton:hover{"
"background-color:#d32f2f;"
"}");
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), this,
SLOT(ReplyFunc(QNetworkReply *)));
}
固定窗口大小。设置背景颜色,设置按钮和下拉框的样式。创建QNetworkAccessManager对象manager,连接信号槽connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(ReplyFunc(QNetworkReply*))
void Translate::paintEvent(QPaintEvent *event) {
Q_UNUSED(event);
QPainter painter(this);
QLinearGradient gradient(0, 0, width(), height());
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::blue);
painter.fillRect(rect(), gradient);
}
重写虚函数时,必须保持函数签名一致。因此就算不使用某个参数,也必须放置在参数列表。用Q_UNUSED(event)标记未使用的参数,避免编译器警告。创建QLinearGradient对象和painter,完成背景的渐变。
void Translate::on_pushButton_Translate_clicked() {
QString inputText = ui->textEdit_InputText->toPlainText();
QString encodedText = QUrl::toPercentEncoding(inputText);
QString appid = "your_appid";
QString secretKey = "your_secretKey";
QString salt = QString::number(QDateTime::currentSecsSinceEpoch());
QString signRaw = appid + inputText + salt + secretKey;
QByteArray md5Hash =
QCryptographicHash::hash(signRaw.toUtf8(), QCryptographicHash::Md5);
QString sign = md5Hash.toHex();
QString toLang =
(ui->comboBox_CE->currentText() == "中文翻译英文") ? "en" : "zh";
QString apiUrl = QString("http://api.fanyi.baidu.com/api/trans/vip/translate"
"?q=%1&from=auto&to=%2&appid=%3&salt=%4&sign=%5")
.arg(encodedText)
.arg(toLang)
.arg(appid)
.arg(salt)
.arg(sign);
QNetworkRequest request;
request.setUrl(QUrl(apiUrl));
manager->get(request);
}
生成URL并发送。
用textEdit_InputText 读取用户输入 的内容。因为url编码中不能直接含有中文和空格,所以要先进行QUrl::toPercentEncoding() 转换,确保中文和空格能正常传输。按照百度翻译 API 的规则,构造签名(signRaw):appid + 原文 + salt + secretKey。其中,appid 和 secretKey 是百度为开发者分配的身份凭证,salt 是当前的时间戳。
然后用 QCryptographicHash::Md5 对签名字符串做 MD5 哈希得到二进制结果。又因为二进制数据不能直接放在 URL 中,所以调用 toHex() 将其转为 16 进制字符串,得到最终的签名(sign)。
最后,将上述所有参数(appid、salt、sign等等)按百度 API 的 URL 格式拼接成完整请求地址并通过 QNetworkAccessManager对象发起 GET 请求。
百度 API 的 URL 格式可以自行通过下述网址查阅。
https://api.fanyi.baidu.com/doc/27

void Translate::ReplyFunc(QNetworkReply *reply) {
ui->textEdit_Result->clear();
QJsonParseError jsonError;
QJsonDocument json = QJsonDocument::fromJson(reply->readAll(), &jsonError);
if (jsonError.error == QJsonParseError::NoError && json.isObject()) {
QJsonObject rootjson = json.object();
if (rootjson.contains("trans_result")) {
QJsonValue resultValue = rootjson.value(QString("trans_result"));
QJsonArray array = resultValue.toArray();
QString strMean = "";
for (int i = 0; i < array.size(); i++) {
QJsonObject explains = array.at(i).toObject();
if (explains.contains("dst")) {
QJsonValue dst = explains.value(QString("dst"));
strMean += dst.toString();
}
}
ui->textEdit_Result->append(strMean);
}
}
ui->textEdit_Record->append(ui->textEdit_InputText->toPlainText() + "->" +
ui->textEdit_Result->toPlainText());
}
处理网络请求的返回结果,并将其显示在UI界面上。
在收到百度翻译 API 的响应后,调用 reply->readAll() 将返回的数据读取为原始 JSON 字符串,并通过 QJsonDocument::fromJson() 转换为JSON 文档对象(真正有JSON结构的数据)。
根据百度接口的规定,返回的数据是标准JSON格式,翻译结果保存在 "trans_result" 数组中。若解析成功,从根对象中取出 trans_result 字段,将其转为 QJsonArray。随后遍历数组中的每个元素(JSON 对象),查找 "dst" 键对应的字符串值(翻译结果)。多个结果会依次拼接,实现处理一次性输入多段文本的情况。最后,将拼接好的翻译结果显示在结果框中,并追加到历史记录。
void Translate::closeEvent(QCloseEvent *event) {
QString strText = ui->textEdit_Record->toPlainText();
QFile file("logfile.txt");
if (file.open(QIODevice::Append | QIODevice::Text)) {
QTextStream out(&file);
out << strText << "\n";
file.close();
}
event->accept();
}

窗口关闭时,把翻译记录写入 logfile.txt 文件,保证翻译记录不会丢失。用textEdit_Record->toPlainText()获取UI界面上的翻译记录,再用QTextStream将其传到所创建的文件对象file(logfile.txt)内。最后关闭文件对象,并接收关闭事件。

被折叠的 条评论
为什么被折叠?



