首页 > 编程笔记 > Qt笔记

Qt程序的字符编码方式

本节会创建一个图形界面 Qt 程序,并故意对源文件使用不恰当的字符编码方式,导致其文本显示控件的汉字乱码。我们会介绍两种纠正方法:
第二种是最为推荐的方式,一劳永逸地解决乱码问题,UTF-8 是 Qt5 默认的编码方式。

乱码的示例程序

首先「猛击这里」下载 qtmess 示例程序,得到的是一个压缩包,解压到比如 D:\QtDemo\qtmess 文件夹里,然后用 QtCreator 打开该项目文件 qtmess.pro,看到项目配置提示界面:

一般选中 Select all kits ,然后点击 Configure Project ,让集成开发环境 QtCreator 自动配置好。

为了让例子尽可能简单,项目里面只有一个源文件 qtmess.cpp ,在项目视图打开该源代码文件,右边编辑器出现以下提示:

编辑器默认是认识 UTF-8 编码的源文件,这个 qtmess.cpp 是在简体中文 Windows 里用记事本编辑的,其汉字编码格式是 GBK,所以上图中文出现乱码。右上角也提示出现解码错误,不能用默认的 UTF-8 格式解码。点击“Select Encoding”按钮,打开源文件编码选择对话框:

对于简体中文,选择 GBK 打头的条目或 GB18030 打头的都可以,windows-936 和其他 CP936(CodePage)、MS936(Microsoft)是一个意思,大字符集 GB18030 也有其他称呼,如 ibm-1392,windows 代码页编号 54936。这里选择 GBK 的条目(GBK 条目有重复的,任选一个),然后点击“按编码重新载入”按钮,文件里的汉字就正常了:

注意 UTF-8 和 GBK 其实对英文和数字都是一样的 ASCII 单字节编码,所以源文件用英文和数字是肯定不乱码,主要是汉字之类的本地语言文字编码显示容易出错。

Windows 系统里一般的记事本、编辑器、VC++ 开发环境等都是默认用 GBK 汉字编码,而 Linux 和 Qt 都是默认用 UTF-8 国际文字编码,所以文本显示乱码一般都是这个原因,从编辑器里选择正确的编码就可以正常显示本地语言文字了。

查看源文件的编码格式

选择源文件编码之后,GBK 编码文件和 UTF-8 编码文件都能正确显示,但怎么从 QtCreator 看到当前文件编码格式呢?这个是可以配置的,让 QtCreator 自动显示。点击菜单“工具”--> “选项”,在选项对话框左边选择“文本编辑器”,右边选择“显示”,看到下图:

选中“Display file encoding”,然后点击“OK”按钮,就可以在编辑器右上角看到当前文件的编码格式:

现在右上角可以看到源文件编码“GBK”了,这其实是一个快捷按钮,打开可以弹出刚才的文件编码对话框的。

关于代码的说明

关于编辑器的编码显示介绍到这,下面解释一下源文件里的内容:
//qtmess.cpp
#include <QApplication>
#include <QTextBrowser>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QString strText = QObject::tr("1234打印汉字");
    QTextBrowser tb;
    tb.setText(strText);
    tb.setGeometry(40, 40, 400, 300);
    tb.show();
   
    return a.exec();
}
代码中包含了 QApplication、QTextBrowser、QDebug 三个头文件,QTextBrowser 是一个只读的文本显示框,一般用于大段文字的显示,并可以选择(Ctrl+A)并复制(Ctrl+C)里面的文本;而之前用的 QLabel 一般用于短文本显示,没有复制文本的功能,QLabel 经常配合其他控件使用,显示相关信息。

在 main() 函数内部:
代码比较简单,接下来我们点击 QtCreator 左下角的绿色三角形运行按钮,编译运行程序,看看效果:

不出意外地,数字显示是正常的,汉字是乱码的,因为 Qt5 默认都是将源文件里的字符串当作 UTF-8 编码处理,GBK 多字节编码的汉字就会乱码。对于纠正乱码,正确的做法是将源文件的编码格式修改成 UTF-8,不推荐的做法是使用 QString::​fromLocal8Bit() 函数实现转码。我们先来看看不推荐的做法。

【不推荐】QString::​fromLocal8Bit() 函数实现转码

我们先采用不改变源文件编码的做法,而是通过修改具体的代码行,使用 QString::​fromLocal8Bit() 函数代替 tr() 函数来实现转码。修改 qtmess.cpp 源文件内容如下:
//qtmess.cpp
#include <QApplication>
#include <QTextBrowser>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QString strText = QString::fromLocal8Bit("1234打印汉字");
    QTextBrowser tb;
    tb.setText(strText);
    tb.setGeometry(40, 40, 400, 300);
    tb.show();
   
    return a.exec();
}
上面将原来的 QObject::tr() 函数替换成了 QString::fromLocal8Bit() 函数,因为只有一个字符串所以替换了一次,如果字符串特别多,那就非常麻烦了。而且变成 QString::fromLocal8Bit() 函数之后,就不能通过检测 tr() 函数进行国际化翻译了,所以这种做法是不推荐的。

点击 QtCreator 左下角运行按钮,看看运行效果:
现在汉字是正常显示的,但代价是修改了代码行,如果字符串很多,那就麻烦了。

【推荐】将源文件改成 UTF-8 编码

将 qtmess.cpp 文件内容改回成原来的,还是使用原先的 QObject::tr() 封装字符串。在 QtCreator 编辑器右上角,点击文件编码的“GBK”字样:

在编码列表里找到“UTF-8”,选中该条目,然后点击右下角的“按编码保存”,QtCreator 会自动将文件内容转换成 UTF-8 格式存储,这样就不需要修改具体的代码行了:

现在点击左下角运行按钮,同样可以看到正常的汉字显示。

本教程以后的全部文件格式都是按照 UTF-8 的编码,这也是 Qt5 默认的源文件编码格式,字符串也应该用 tr 函数封装,方便做国际化翻译。如果项目有面向国际化的要求,程序源代码里应该全部用英文和数字等 ASCII 码字符,尽量少用汉字,应当将汉字作为一个语言的翻译文件程序。本教程大多数例子都是不符合国际化标准的,因为方便大家看,作者自己也省事。读者实际的国际化项目开发中应该按照全英文的来写代码,然后将英文界面翻译成多种语言文字的。

所有教程

优秀文章