【新手】基于C++Qt5通过调用百度翻译API制作简易翻译工具

基于C++Qt5通过调用百度翻译API制作简易翻译工具


写在前面

先看看效果图
在这里插入图片描述

机缘巧合我发现了百度翻译API,也看了很多大佬用这个API做的项目。恰我的C++实验课的大作业是做一个项目,我就想到了做一个简易的翻译工具。

实现方法:通过封装一个生成url的类,对传入的需要翻译的内容生产相应的url,然会用QNetworkRequest类发送get请求,对请求返回的结果正则表达式解析和utf-8转码就得到了翻译结果
注意:翻译记录功能目前还没实现,不是因为很难,是因为很懒


步骤:

1.注册百度翻译开放平台账号并开通翻译服务

进入百度翻译开放平台官网,登录或注册


开通翻译服务

这里应该还要求实名认证才能开通服务


获取appid和密钥
在这里插入图片描述

2.下载安装Qt5和QtCreator (windows)

2.1下载Qt5

Qt5可以去下面的网站下载
[https://download.qt.io/archive/qt/]
(https://download.qt.io/archive/qt/)
在这里插入图片描述

在这里插入图片描述

也可以用迅雷下载我下载好的Qt5.12.10
链接:https://pan.xunlei.com/s/VMT-alRj3yvgWqrYNgWSPYeJA1
提取码:5b9p

2.2安装Qt5和QtCreator

在这里插入图片描述
在这里插入图片描述
注册后他会发邮件给你,按照它提示的步骤完成就行,我就不演示了,注册好后再回来。

在这里插入图片描述
在这里插入图片描述
接下来是选配环节了,建议电脑内存充足的选择全选,说不定以后能用上
在这里插入图片描述
下面的选择是安装Qtcreator
在这里插入图片描述
配置完成后点击下一步,来到下面的界面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个安装要挺久的,反正我装了30分钟才装好。
装好之后在wimdows菜单找到刚刚创建的那个文件夹拉到最下面,如下图
在这里插入图片描述
到这里Qt5算是装好了,可以开始创建我们的项目了

2.3创建项目

打开QtCreator后
选择创建新项目
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
创建完成后
在这里插入图片描述
在这里插入图片描述
跑不了的可以按步骤再多试几次

最后按下面的步骤添加

QT       += network

这是访问必须的配置
在这里插入图片描述
到这里创建项目的准备工作就完成了

3.封装生成Url类

3.1百度翻译文档阅读

如果还没看过百度翻译api的文档建议先去看看,了解url的生产有助于下面代码的理解
百度翻译api文档

3.2编写代码

以下是实现生产url类的源码
Translator.h

#ifndef TANSLATOR_H
#define TANSLATOR_H

#include <iostream>
#include <QString>
#include <time.h>
#include <QTextCodec>
#include <QDebug>
#include <QObject>
#include "MD5.h"

using namespace std;
class Translator: public QObject
{
    
    
    Q_OBJECT
private:
    //支持7个翻译目标语种的标号
    string lan[7]={
    
    "en","zh","fra","de","kor","jp","th"};
    int index;      //选择语种的下标
    /* 因为百度翻译需要一个MD5加密的签名
     * 但是我找到的MD5加密的方法都只支持string类型
     * 所以这里先生产string类型url再转成Qstring
     * ps:不知道string和Qstring的区别可以去补一下课*/
    string myurl;   //存放string类型url
    string appid;   //appid
    QString qstr;   //传入的Qstring类型翻译的内容,需要转成string类型
    string q;       //string类型翻译的内容
    string from;    //翻译内容的语种,一般为‘auto’
    string to;      //翻译目标语种
    string salt;    //一串随机数,我是用时间戳当成随机数
    string secret_key;   //密钥
    string sign;    //MD5加密的签名
    QString url;    //Qstring类型url


public:
    Translator();     //默认构造函数
    Translator(const QString &);     //构造函数
    QString GetUrl();   //生产url的方法
    void SetQstr(const QString &);   //设置需要翻译内容的函数
    void SetIndex(const int&);      //设置翻译目标语种的函数



};

#endif // TANSLATOR_H

Translator.cpp

#include "Translator.h"

#if _MSC_VER >=1600    // MSVC2015>1899,对于MSVC2010以上版本都可以使用
#pragma execution_character_set("utf-8")
#endif
Translator::Translator(){
    
    

}
Translator::Translator(const QString &qerry)
    :qstr(qerry)
{
    
    
    q = qstr.toStdString();
    index = 0;
}

void Translator::SetQstr(const QString &qstring){
    
    
    qstr = qstring;
    q = qstr.toStdString();

}
void Translator::SetIndex(const int& in){
    
    
    index = in;
}
QString Translator::GetUrl(){
    
    
    //制作签名
    myurl = "https://fanyi-api.baidu.com/api/trans/vip/translate?";
    appid = "1212121212";  //你的appid
    from = "auto";
    to = lan[index];  //选择目标语种
    time_t myt = time(NULL);  //获取时间戳
    salt = to_string(myt);
    secret_key = "12121212212";  //你的密钥
    sign = "";
    //签名拼接
    sign.append(appid);
    sign.append(q);
    sign.append(salt);
    sign.append(secret_key);

    //签名MD5加密
    MD5 md5 = MD5(sign);
    sign = md5.outstr(32).c_str();

    //制作url
    myurl.append("&q=");
    myurl.append(q);
    myurl.append("&from=");
    myurl.append(from);
    myurl.append("&to=");
    myurl.append(to);
    myurl.append("&appid=");
    myurl.append(appid);
    myurl.append("&salt=");
    myurl.append(salt);
    myurl.append("&sign=");
    myurl.append(sign);
    //string转Qstring
    url=QString::fromStdString(myurl);
    return url;
}

下面附上MD5加密的源码,来源于网络
MD5.h

#include <iostream>
#include <windows.h>
using namespace std;
typedef unsigned char uchar;
typedef unsigned long ulong;

//步函数
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
//循环左移
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
//  四轮操作
#define FF(a, b, c, d, mj, s, ti) { (a) += F ((b), (c), (d)) + (mj) + ti; (a) = ROL ((a), (s)); (a) += (b);}
#define GG(a, b, c, d, mj, s, ti) { (a) += G ((b), (c), (d)) + (mj) + ti; (a) = ROL ((a), (s)); (a) += (b);}
#define HH(a, b, c, d, mj, s, ti) { (a) += H ((b), (c), (d)) + (mj) + ti; (a) = ROL ((a), (s)); (a) += (b);}
#define II(a, b, c, d, mj, s, ti) { (a) += I ((b), (c), (d)) + (mj) + ti; (a) = ROL ((a), (s)); (a) += (b);}

class MD5 {
    
    
public:
    MD5(const string& str);
    const uchar* getDigest();	// 获取生成的摘要
    string outstr(int);			// 返回字符串
private:
    void generate(const uchar* input, int length);
    void change(const uchar block[64]);							// 四轮操作
    void encode(const ulong* input, uchar* output, int length);	// uchar to ulong
    void decode(const uchar* input, ulong* output, int length); // ulong to uchar

    ulong reg[4];		// ABCD
    ulong count[2];	    // 长度扩充
    uchar buffer[64];	// 输入buffer
    uchar digest[16];	// 生成的摘要
    bool end_flag;		// 结束标志
    static const uchar padding[64];
    static const char hex[16];
};

MD5.cpp

#include <MD5.h>

const uchar MD5::padding[64] = {
    
     0x80 };	// 初始化附加填充 1000 0000, 设置最高位为1
const char MD5::hex[16] = {
    
     '0', '1', '2', '3','4', '5', '6', '7','8', '9', 'a', 'b','c', 'd', 'e', 'f' };

MD5::MD5(const string& str) {
    
    
    end_flag = false;
    count[0] = count[1] = 0; // 重置bits个数
    // 初始化链接变量(高位->低位)
    /*
     * 错误的赋值,注意高低位
    reg[0] = 0x01234567;
    reg[1] = 0x89abcdef;
    reg[2] = 0xfedcba98;
    reg[3] = 0x76543210;
    */
    reg[0] = 0x67452301;
    reg[1] = 0xefcdab89;
    reg[2] = 0x98badcfe;
    reg[3] = 0x10325476;
    generate((uchar*)const_cast<char*>(str.c_str()), str.length());
}

/**
 * 获取摘要
 */
const uchar* MD5::getDigest() {
    
    
    if (!end_flag) {
    
    
        end_flag = true;
        uchar bits[8];
        ulong _reg[4];		// 旧reg
        ulong _count[2];	// 旧count
        ulong index, padLen;
        memcpy(_reg, reg, 16);		// 复制内存,将_reg内存地址的起始位置开始拷贝16字节到reg起始位置中
        memcpy(_count, count, 8);	// 将原始消息长度以64比特(8字节)复制到count后
        encode(count, bits, 8);
        /* Pad out to 56 mod 64. */
        index = (ulong)((count[0] >> 3) & 0x3f);
        padLen = (index < 56) ? (56 - index) : (120 - index);
        generate(padding, padLen);
        generate(bits, 8);
        encode(reg, digest, 16);
        /* 重新存储reg和count */
        memcpy(reg, _reg, 16);
        memcpy(count, _count, 8);
    }
    return digest;
}


void MD5::generate(const uchar* input, int length) {
    
    
    ulong i, index, partLen;
    end_flag = false;
    index = (ulong)((count[0] >> 3) & 0x3f);
    if ((count[0] += ((ulong)length << 3)) < ((ulong)length << 3))
        count[1]++;
    count[1] += ((ulong)length >> 29);
    partLen = 64 - index;
    if (length >= partLen) {
    
    
        memcpy(&buffer[index], input, partLen);
        change(buffer);	//分组处理,四轮操作
        for (i = partLen; i + 63 < length; i += 64)
            change(&input[i]);
        index = 0;
    }
    else {
    
    
        i = 0;
    }
    // 内存拷贝
    memcpy(&buffer[index], &input[i], length - i);
}

/**
 * 四轮变换操作
 */
void MD5::change(const uchar block[64]) {
    
    
    ulong a = reg[0],
        b = reg[1],
        c = reg[2],
        d = reg[3],
        m[16];

    decode(block, m, 64);	// uchar 转 ulong

    FF(a, b, c, d, m[0], 7, 0xd76aa478);
    FF(d, a, b, c, m[1], 12, 0xe8c7b756);
    FF(c, d, a, b, m[2], 17, 0x242070db);
    FF(b, c, d, a, m[3], 22, 0xc1bdceee);
    FF(a, b, c, d, m[4], 7, 0xf57c0faf);
    FF(d, a, b, c, m[5], 12, 0x4787c62a);
    FF(c, d, a, b, m[6], 17, 0xa8304613);
    FF(b, c, d, a, m[7], 22, 0xfd469501);
    FF(a, b, c, d, m[8], 7, 0x698098d8);
    FF(d, a, b, c, m[9], 12, 0x8b44f7af);
    FF(c, d, a, b, m[10], 17, 0xffff5bb1);
    FF(b, c, d, a, m[11], 22, 0x895cd7be);
    FF(a, b, c, d, m[12], 7, 0x6b901122);
    FF(d, a, b, c, m[13], 12, 0xfd987193);
    FF(c, d, a, b, m[14], 17, 0xa679438e);
    FF(b, c, d, a, m[15], 22, 0x49b40821);

    GG(a, b, c, d, m[1], 5, 0xf61e2562);
    GG(d, a, b, c, m[6], 9, 0xc040b340);
    GG(c, d, a, b, m[11], 14, 0x265e5a51);
    GG(b, c, d, a, m[0], 20, 0xe9b6c7aa);
    GG(a, b, c, d, m[5], 5, 0xd62f105d);
    GG(d, a, b, c, m[10], 9, 0x2441453);
    GG(c, d, a, b, m[15], 14, 0xd8a1e681);
    GG(b, c, d, a, m[4], 20, 0xe7d3fbc8);
    GG(a, b, c, d, m[9], 5, 0x21e1cde6);
    GG(d, a, b, c, m[14], 9, 0xc33707d6);
    GG(c, d, a, b, m[3], 14, 0xf4d50d87);
    GG(b, c, d, a, m[8], 20, 0x455a14ed);
    GG(a, b, c, d, m[13], 5, 0xa9e3e905);
    GG(d, a, b, c, m[2], 9, 0xfcefa3f8);
    GG(c, d, a, b, m[7], 14, 0x676f02d9);
    GG(b, c, d, a, m[12], 20, 0x8d2a4c8a);

    HH(a, b, c, d, m[5], 4, 0xfffa3942);
    HH(d, a, b, c, m[8], 11, 0x8771f681);
    HH(c, d, a, b, m[11], 16, 0x6d9d6122);
    HH(b, c, d, a, m[14], 23, 0xfde5380c);
    HH(a, b, c, d, m[1], 4, 0xa4beea44);
    HH(d, a, b, c, m[4], 11, 0x4bdecfa9);
    HH(c, d, a, b, m[7], 16, 0xf6bb4b60);
    HH(b, c, d, a, m[10], 23, 0xbebfbc70);
    HH(a, b, c, d, m[13], 4, 0x289b7ec6);
    HH(d, a, b, c, m[0], 11, 0xeaa127fa);
    HH(c, d, a, b, m[3], 16, 0xd4ef3085);
    HH(b, c, d, a, m[6], 23, 0x4881d05);
    HH(a, b, c, d, m[9], 4, 0xd9d4d039);
    HH(d, a, b, c, m[12], 11, 0xe6db99e5);
    HH(c, d, a, b, m[15], 16, 0x1fa27cf8);
    HH(b, c, d, a, m[2], 23, 0xc4ac5665);

    II(a, b, c, d, m[0], 6, 0xf4292244);
    II(d, a, b, c, m[7], 10, 0x432aff97);
    II(c, d, a, b, m[14], 15, 0xab9423a7);
    II(b, c, d, a, m[5], 21, 0xfc93a039);
    II(a, b, c, d, m[12], 6, 0x655b59c3);
    II(d, a, b, c, m[3], 10, 0x8f0ccc92);
    II(c, d, a, b, m[10], 15, 0xffeff47d);
    II(b, c, d, a, m[1], 21, 0x85845dd1);
    II(a, b, c, d, m[8], 6, 0x6fa87e4f);
    II(d, a, b, c, m[15], 10, 0xfe2ce6e0);
    II(c, d, a, b, m[6], 15, 0xa3014314);
    II(b, c, d, a, m[13], 21, 0x4e0811a1);
    II(a, b, c, d, m[4], 6, 0xf7537e82);
    II(d, a, b, c, m[11], 10, 0xbd3af235);
    II(c, d, a, b, m[2], 15, 0x2ad7d2bb);
    II(b, c, d, a, m[9], 21, 0xeb86d391);

    reg[0] += a;
    reg[1] += b;
    reg[2] += c;
    reg[3] += d;
}

/**
 * ulong 转 uchar
 */
void MD5::encode(const ulong* input, uchar* output, int length) {
    
    
    for (int i = 0, j = 0; j < length; i++, j += 4) {
    
    
        output[j] = (uchar)(input[i] & 0xff);
        output[j + 1] = (uchar)((input[i] >> 8) & 0xff);
        output[j + 2] = (uchar)((input[i] >> 16) & 0xff);
        output[j + 3] = (uchar)((input[i] >> 24) & 0xff);
    }
}

/**
 * uchar 转 ulong
 */
void MD5::decode(const uchar* input, ulong* output, int length) {
    
    

    for (int i = 0, j = 0; j < length; i++, j += 4) {
    
    
        output[i] = ((ulong)input[j]) | (((ulong)input[j + 1]) << 8) | (((ulong)input[j + 2]) << 16) | (((ulong)input[j + 3]) << 24);
    }
}

string MD5::outstr(int length = 32) {
    
    
    const uchar* input = getDigest();
    string str;
    //str.reserve(length << 1);
    for (int i = 0; i < 16; i++) {
    
    
        int t = input[i];
        int a = t / 16;
        int b = t % 16;
        str.append(1, hex[a]);
        str.append(1, hex[b]);
    }
    if (16 == length) {
    
    
        str = str.substr(9 - 1, 16);
    }
    return str;
}

/**
 * GB2312转Unicode,解决中文出错问题
 * 此处代码来源于网络。
 */
string G2U(string str) {
    
    
    int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
    wchar_t* pwBuf = new wchar_t[nwLen + 1];
    ZeroMemory(pwBuf, nwLen * 2 + 2);
    ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
    int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    char* pBuf = new char[nLen + 1];
    ZeroMemory(pBuf, nLen + 1);
    ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    std::string retStr(pBuf);
    delete[]pwBuf;
    delete[]pBuf;
    pwBuf = NULL;
    pBuf = NULL;
    return retStr;
}

4.使用Qt5制作简易图形化界面

在设计中简单设计自己喜欢的界面,需要注意的是要记住部分控件的id,如编辑框和按钮等,建议自己重命名一下
拖拽设计这里就不演示了,挺简单的
在这里插入图片描述
下面附上ui代码
mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>640</width>
    <height>581</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>640</width>
    <height>581</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>640</width>
    <height>581</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QComboBox" name="comboBox">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>190</y>
      <width>121</width>
      <height>31</height>
     </rect>
    </property>
    <property name="minimumSize">
     <size>
      <width>121</width>
      <height>31</height>
     </size>
    </property>
    <item>
     <property name="text">
      <string>英语</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>中文</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>法语</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>德语</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>韩语</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>日语</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>泰语</string>
     </property>
    </item>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>30</y>
      <width>91</width>
      <height>21</height>
     </rect>
    </property>
    <property name="minimumSize">
     <size>
      <width>91</width>
      <height>21</height>
     </size>
    </property>
    <property name="text">
     <string>翻译记录:</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_3">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>150</y>
      <width>121</width>
      <height>31</height>
     </rect>
    </property>
    <property name="minimumSize">
     <size>
      <width>121</width>
      <height>31</height>
     </size>
    </property>
    <property name="text">
     <string>目标语种:</string>
    </property>
   </widget>
   <widget class="QLabel" name="labeltips">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>49</y>
      <width>131</width>
      <height>101</height>
     </rect>
    </property>
    <property name="minimumSize">
     <size>
      <width>131</width>
      <height>101</height>
     </size>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="textFormat">
     <enum>Qt::AutoText</enum>
    </property>
    <property name="alignment">
     <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>450</x>
      <y>260</y>
      <width>161</width>
      <height>81</height>
     </rect>
    </property>
    <property name="text">
     <string>翻译</string>
    </property>
   </widget>
   <widget class="QSplitter" name="splitter_3">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>10</y>
      <width>381</width>
      <height>541</height>
     </rect>
    </property>
    <property name="orientation">
     <enum>Qt::Vertical</enum>
    </property>
    <widget class="QSplitter" name="splitter">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <widget class="QLabel" name="label">
      <property name="minimumSize">
       <size>
        <width>61</width>
        <height>20</height>
       </size>
      </property>
      <property name="text">
       <string>原文:</string>
      </property>
     </widget>
     <widget class="QTextEdit" name="textEdit">
      <property name="undoRedoEnabled">
       <bool>true</bool>
      </property>
      <property name="html">
       <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="placeholderText">
       <string>请输入</string>
      </property>
     </widget>
    </widget>
    <widget class="QSplitter" name="splitter_2">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <widget class="QLabel" name="label_5">
      <property name="minimumSize">
       <size>
        <width>71</width>
        <height>21</height>
       </size>
      </property>
      <property name="text">
       <string>译文:</string>
      </property>
     </widget>
     <widget class="QTextEdit" name="textdisplay">
      <property name="enabled">
       <bool>true</bool>
      </property>
     </widget>
    </widget>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>640</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

5.编写逻辑代码

附上逻辑源码
里面注释清晰明了
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <regex>
#include <atlstr.h>
#include <vector>
#include <QMainWindow>
#include <QNetworkReply>

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    
    
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);  //构造函数
    QString unicodeToUtf8(QString);  //unicode转utf-8,用于处理返回数据
    QString myregex(const QString &str);   //正则处理函数,用于解析返回数据,这里也可以使用json解析数据
    ~MainWindow();

private:
    Ui::MainWindow *ui;     //初始化ui


public slots:
    void parsingJson(QNetworkReply * reply);   //get请求完成后触发槽函数     
    void ClickButton();  //翻译按钮触发槽函数
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#if _MSC_VER >=1600    // MSVC2015>1899,对于MSVC2010以上版本都可以使用
#pragma execution_character_set("utf-8")  //设置编码格式为utf-8,可能会出现乱码
#endif
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    
    
    //初始化ui
    ui->setupUi(this);
    setWindowTitle("随便翻译");   //设置窗口标题
    setFixedSize(640,581);      //设置窗口大小

    ui->labeltips->setText("共翻译:10次\n\n成功:5次");      //懒得实现的翻译记录功能
    ui->textdisplay->setReadOnly(true);        //我是用TextEdit来展示翻译结果,所以这里要设置为只读模式

    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(ClickButton()));   //翻译按钮信号和槽函数连接,这里是qt4风格的连接

}
void MainWindow::ClickButton(){
    
    
    int index=0;
    index=ui->comboBox->currentIndex();   //获取下拉选择框中选中的语种
    QString str = ui->textEdit->toPlainText();   //获取输入框中的内容
//    qDebug()<<str;
    translator.SetQstr(str);     //传入需要翻译
    translator.SetIndex(index);  //传入下标
    QString url = translator.GetUrl();     //获取url
//    qDebug()<<url;
    //1. 创建一个请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    //2. 创建一个管理器
    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
   // 3. 连接请求结束信号
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(parsingJson(QNetworkReply*)));
    //4. 发送GET请求
    manager->get(request);
}

//槽函数,处理返回的数据
void MainWindow::parsingJson(QNetworkReply * reply)
{
    
    
    if(reply->error() == QNetworkReply::NoError){
    
       //判断是否请求成功
        QString all = reply->readAll();   //读出返回数据
        qDebug() << all ;   //打印出来会发现中文和一些外文是Unicode编码的转义字符,如\\u187d
        QString re = myregex(all);   //解析出翻译结果,即取出dst字段
        qDebug()<<re;
        QString res = unicodeToUtf8(re);    //unicode转utf8
        qDebug()<<res ;
        ui->textdisplay->setText(res);  //更新控件上的内容
    }
    else{
    
    
        qDebug() << reply->errorString() << " error " << reply->error();
    }
}

QString MainWindow::myregex(const QString &qstr){
    
       //正则解析函数,这里就不解释了,不会正则的可以去补一下课
    string ans;
    string str = qstr.toStdString();
    string pattern = "\"(.+?)\"";
    regex e("\\[(.*)\\]");
    regex r(pattern);
    smatch m;
    regex_search(str, m, e);

    string temp = m[1];
    auto res = vector<string>(9);

    sregex_iterator pos(temp.cbegin(), temp.cend(), r), end;
    for (; pos != end; ++pos) {
    
    
        res.push_back(pos->str(1));
    }
    for (auto temp : res)
        ans = temp;

    return QString::fromStdString(ans);
}

QString MainWindow::unicodeToUtf8(QString str) //unicode转utf8
{
    
    
    QString result;
    int index = str.indexOf("\\u");
    qDebug()<<index;
    //判断是否存在为转移字符,实践表明只有英文字母是可以正常显示不需要转码的
    if(index!=-1){
    
       
        /* 判断字符串是否全为转义字符,实践表明中文和韩文等全是转移
         * 法语和德语只有个别特殊符号是转义字符
         *  */
        if(index==0){
    
       //全为转义
            while (index != -1){
    
    
                QString s1 = str.mid(index + 2, 4);
                result.append(s1.toUShort(0, 16));
                index = str.indexOf("\\u", index+5);
            }
            return result.toUtf8().constData();
        }
        else{
    
       //部分转义
            while (index != -1){
    
    
                QString s1 = str.mid(index + 2, 4);
                result=s1.toUShort(0, 16);
                str.replace(index-1,7,result.toUtf8().constData());
                index = str.indexOf("\\u", index+5);
            }
            return str;
        }
    }
    return str;
//    return result.toUtf8().constData();
}

MainWindow::~MainWindow()
{
    
    
    delete ui;
}

最后还有启动的main函数

#include "mainwindow.h"
#include <QApplication>


int main(int argc, char *argv[])
{
    
    
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

这样一个简易的翻译工具就做好了

补充:编码转码和一些报错处理

1.QtCreator默认的编码格式是utf-8
可以通过以下方式查看或修改
工具->选项,如下图
在这里插入图片描述
2.计算机会把utf-8或其他格式的数据转成Unicode,便于通信,这也是get请求返回的数据是Unicode格式的原因,所以在解析出dst字段后还要进行转码。

3.一下是我开发过程中遇到的一些问题,以及参考的一些优秀博主的解决方法

报错:No such slot
参考下面的解决方法
QT常见错误 | No such slot错误分析与解决

报错:

qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed

可以参考我的另一篇文章
https://blog.csdn.net/yyy90/article/details/113762890

总结一下

这是应该是我做的第一项目,我的c++作业是用VS2019+MFC做的,但是在编码格式这块没弄明白做的比较拉跨,而且比较麻烦不像Qt5有自带的访问网络的库,所以想用Qt5再做一次。
Qt小白,欢迎大家批评指正!

猜你喜欢

转载自blog.csdn.net/yyy90/article/details/113762827