本節會創建一個圖形界面 Qt 程序,並故意對源文件使用不恰當的字符編碼方式,導致其文本顯示控件的漢字亂碼。我們會介紹兩種糾正方法:
- 第一種是不修改源代碼文件編碼格式,通過 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 碼字符,盡量少用漢字,應當將漢字作為一個語言的翻譯文件程序。本教程大多數例子都是不符合國際化標准的,因為方便大家看,作者自己也省事。讀者實際的國際化項目開發中應該按照全英文的來寫代碼,然后將英文界面翻譯成多種語言文字的。