• Qt项目实战 杂谈一二:中文乱码事情小,处理不好头发少


    Qt开发者来说,特别是初学者,往往最头疼的是编码的问题。举个例子。
    1、控件上设置中文标签,发现显示出来是乱码?怎么解决。如果标签是常量字符串(含中文),怎么处理。如果标签是变量,且可能包含字符串,又咋处理?
    2、Qt应用与其他应用存在进程间交互,数据中不可避免的包含中文字符。Qt应用譬如使用的是utf8编码,其他应用可能是使用unicode编码或者其他编码,数据交互过程中的中文乱码问题怎么处理?

    先只抛出这两个问题。看看有没有戳中朋友们的肋骨。
    然后我们说说这两个问题怎么在实际的项目开发过程中避免和解决。

    问题一解决方案:
    1、控件上显示中文标签乱码问题。
    常量字符标签(含中文)的显示方式
    (1)【方案一】使用Qt国际化,代码中全部用英文,然后加ts翻译成中文。这种方法不是不可以,但是很stupid,为了解决小小乱码的问题,还要引入翻译模块,简直就是高射炮打蚊子,好么。当然,如果应用本身有国际化需求,对应发布国际市场,那你这么干也无可厚非。
    (2)【方案二】 采用如下方式声明和定义常量字符串标签名:

    QStringLiteral("这是常量字符串");
    
    • 1

    如果只是按照上面的方式去设置,譬如:

    label->setText(QStringLiteral("这是常量字符串"));
    
    • 1

    你发现输出展示的仍是乱码岂不是要跟我扯皮。还有两个关键的步骤,你要注意:
    1、通常,我们默认编码设置成UTF-8 的模式【重要!重要!】
    在这里插入图片描述

    2、当前页,在代码编辑区右键鼠标,选择最下面的 ”add Utf-8 bom” 【这里非常重要,估计很多几年开发经验的Qt从业者也未必会注意到】
    在这里插入图片描述
    另外,一个好的项目一定要注意编码的统一,别一会儿搞个utf8,一回儿搞个gbk或者其他的编码,弄来弄去,项目越来越烂,到最后维护成本越来越高,开发者也被搞的头疼。

    问题二解决方案:
    1、其实解决这个问题并不只是需要编码层面,更加要注意的是项目管理层面(代码管理),我们在设计之初,就要严格要求编码的一致性。
    譬如,Qt应用(作为主应用)与其他不同编码的应用进程间数据交互,我们规定好,Qt应用方接收数据和输出数据必须为utf8编码,定义数据传交互数据类型为char字符串(单字节,宽字节也必须转单字节后再交互)。

    附一个转换方法:

    std::string stringToUTF8(const std::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 strRet(pBuf);
    
        delete []pwBuf;
        delete []pBuf;
        pwBuf = NULL;
        pBuf  = NULL;
    
        return strRet;
    }
    
    std::string UTF8ToString(const std::string& str)
    {
        int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
        wchar_t* pwBuf = new wchar_t[nwLen + 1];
        memset(pwBuf, 0, nwLen * 2 + 2);
        MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
        int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
        char* pBuf = new char[nLen + 1];
        memset(pBuf, 0, nLen + 1);
        WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    
        std::string strRet = pBuf;
    
        delete []pBuf;
        delete []pwBuf;
        pBuf = NULL;
        pwBuf = NULL;
    
        return strRet;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    其他应用根据此协议来自主转换对应编码即可(当然,这里有个条件,Qt应用必须为主应用,否则一个子应用没有必要这么强势)。
    在这里插入图片描述
    这一步在项目设计之初就规划好,后续会避免编码的坑。尤其是多应用交互的场景。

  • 相关阅读:
    Selenium操控元素
    二叉树进阶
    如何解决3d max渲染效果图全白这类异常问题?
    浅论供水管理中产销差率与漏水率的比较和应用
    LQ0015 质因数个数【数论】
    基于Python机器学习、深度学习提升气象、海洋、水文领域实践应用
    【深度学习实验】循环神经网络(四):基于 LSTM 的语言模型训练
    PostGIS简单使用
    react处理跨域
    vite项目启动use `--host` to expose
  • 原文地址:https://blog.csdn.net/weixin_39568531/article/details/126541127