Qt程序的字符编码方式
本节会创建一个图形界面 Qt 程序,并故意对源文件使用不恰当的字符编码方式,导致其文本显示控件的汉字乱码。我们会介绍两种纠正方法:
第二种是最为推荐的方式,一劳永逸地解决乱码问题,UTF-8 是 Qt5 默认的编码方式。
一般选中 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 国际文字编码,所以文本显示乱码一般都是这个原因,从编辑器里选择正确的编码就可以正常显示本地语言文字了。
选中“Display file encoding”,然后点击“OK”按钮,就可以在编辑器右上角看到当前文件的编码格式:
现在右上角可以看到源文件编码“GBK”了,这其实是一个快捷按钮,打开可以弹出刚才的文件编码对话框的。
在 main() 函数内部:
代码比较简单,接下来我们点击 QtCreator 左下角的绿色三角形运行按钮,编译运行程序,看看效果:
不出意外地,数字显示是正常的,汉字是乱码的,因为 Qt5 默认都是将源文件里的字符串当作 UTF-8 编码处理,GBK 多字节编码的汉字就会乱码。对于纠正乱码,正确的做法是将源文件的编码格式修改成 UTF-8,不推荐的做法是使用 QString::fromLocal8Bit() 函数实现转码。我们先来看看不推荐的做法。
点击 QtCreator 左下角运行按钮,看看运行效果:
现在汉字是正常显示的,但代价是修改了代码行,如果字符串很多,那就麻烦了。
在编码列表里找到“UTF-8”,选中该条目,然后点击右下角的“按编码保存”,QtCreator 会自动将文件内容转换成 UTF-8 格式存储,这样就不需要修改具体的代码行了:
现在点击左下角运行按钮,同样可以看到正常的汉字显示。
本教程以后的全部文件格式都是按照 UTF-8 的编码,这也是 Qt5 默认的源文件编码格式,字符串也应该用 tr 函数封装,方便做国际化翻译。如果项目有面向国际化的要求,程序源代码里应该全部用英文和数字等 ASCII 码字符,尽量少用汉字,应当将汉字作为一个语言的翻译文件程序。本教程大多数例子都是不符合国际化标准的,因为方便大家看,作者自己也省事。读者实际的国际化项目开发中应该按照全英文的来写代码,然后将英文界面翻译成多种语言文字的。
- 第一种是不修改源代码文件编码格式,通过 QString::fromLocal8Bit() 函数在程序运行时转码;
- 第二种是直接将源代码文件整体转换成 UTF-8 编码,就不需要修改具体的代码行了。
第二种是最为推荐的方式,一劳永逸地解决乱码问题,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() 函数内部:
- 第一句定义了 Qt 应用程序入口;
- 第二句定义了一个 strText 字符串对象,里面有数字和汉字;
- 第三句定义了 QTextBrowser 对象 tb,就是本程序的图形窗口;
- 第四句设置文本框的文本内容为 strText ;
- 第五句设置文本框的位置(屏幕左上角坐标 40,40)和尺寸(400*300);
- 第六句是显示本程序的窗口;
- 最后一句是进入应用程序的事件循环,直到退出。
代码比较简单,接下来我们点击 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 码字符,尽量少用汉字,应当将汉字作为一个语言的翻译文件程序。本教程大多数例子都是不符合国际化标准的,因为方便大家看,作者自己也省事。读者实际的国际化项目开发中应该按照全英文的来写代码,然后将英文界面翻译成多种语言文字的。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算