qt中文編碼(好多方法)


qt中文編碼

 

來源:http://www.cublog.cn/u1/59481/showart_1947231.html 

 

 

 

前些日子,被編碼折磨了一段時間,總結一下Qt中的編碼。

【Qt 編碼簡單實驗】

首先,Qt中得QString 類對字符串進行了封裝,其內部使用Unicode對傳入的串進行編碼。這樣一來,QString就可以處理絕大多數的國際語言。將QString中的字符根據語言翻譯的過程,也就是Qt 的Translater針對程序中使用含有的tr("XXXXX"),進行翻譯的過程。由於QString的Unicode編碼,和本地系統的編碼不一定是一致的(比如系統采用的GB2312的編碼)。這樣的話,就不能直接使用類似QString str("漢字")這樣的方法來存儲本地的漢字,是有問題的。

<系統是使用GB2312編碼的>

【試驗1】

QString str("漢字");

std::cout << "Straight Output:" << str << endl;

std::cout << "Local Output:" << str.local8Bit() << endl;

std::cout << "Unicode Output:" << str.unicode() << endl;

結果如下:

漢字 (正確)

@#$% (亂碼)

@#$% (亂碼)

【試驗2】

QString str = QString::fromLocal8Bit("漢字");

std::cout << "Straight Output:" << str << endl;

std::cout << "Local Output:" << str.local8Bit() << endl;

std::cout << "Unicode Output:" << str.unicode() << endl;

結果如下:

@#$% (亂碼)

漢字 (正確)

@#$% (亂碼)

首先說試驗1,因為str采用Unicode編碼,中文實際上沒有經過任何的編碼轉換直接存到str中,所以存入的Unicode已經是錯誤的(GB編碼的字符按照Unicode存的)。但是為什么第一個會正常顯示呢?因為標准輸入輸出是不進行任何的編碼解碼工作的,字符串由本地系統讀取時使用本地的字符集GB2312進行解碼,因為存入的字符串“漢字”正好是GB2312編碼的,正好得到了正確地結果!這有點負負得正的味道!QString只是充當了一個容器,里面存的是不正確的值。

對於試驗2來說,使用fromLocal8Bit()函數,實現了從本地字符集GB到Unicode的轉換,所以存在QString中的字符串是經過轉換的正確編碼。輸出的時候,要正確顯示,只能是再轉為本地的字符編碼,也就是使用local8Bit()轉換。由於存入QString的是正確的值,就可以進行包括國際化在內的許多工作!( 注意本地LANGUAGE環境變量!)

【Qt國際化的問題】

在文本顯示上,Qt 使用了Unicode 作為內部編碼,為了程序的國際化,通常我們在文本顯示的地方不直接輸入本地字符,用英文代替,比如要編寫一中文界面的 Qt 程序,應該在程序中使用英文,程序編寫完成后,把文本提取出來翻譯。對於需要翻譯的地方,首先是在該文本處用tr()函數標識,同時制作出.qm信息文件,並在程序中加入QTranslator即可。

比如我們在某一程序中有如下語句: setCaption(tr(“main window”)) 為了顯示中文,有兩種方法:

方法一:

1. 修改工程文件,加上TRANSLATIONS = xxx.ts

2. lupdate 工程文件名

3. 用linguist編輯剛生成的xxx.ts文件並保存

4. lrelease 工程文件名 xxx.qm

5. 在main.cpp中加入QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

6. qApp->setFont(font1);

7. QTranslator *translator = new QTranslator(0);

8. translator->load("xxx.qm",".");

9. qApp->installTranslator(translator);

方法二:

1. findtr 文件名(通常為CPP文件) > xxx.po

2. 編輯po文件,其中charset需由iso-8859-1改為GB2312,然后將“main window”翻譯成“主窗口”

3. msg2qm –scope zh_CN.GB2312 xxx.po xxx.qm

4. 在main.cpp中加入QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

5. qApp->setFont(font1);

6. QTranslator *translator = new QTranslator(0);

7. translator->load("xxx.qm",".");

8. qApp->installTranslator(translator);

方法三:

有時我們只是提供給本地用戶使用,無需國際化,QT提供這一支持,在QT中有許多本地字符集同unicode的轉換引擎,他們皆為QTextCodec的派生類,如QGbkCodec、QJisCodec, QHebrewCodec等。如:

QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

qApp->setFont(font1);

QString caption=“主窗口“;

QTextCodec *gk_codec=QTextCodec::codecForName(“GBK”);

setCaption(gk_codec->toUnicode(caption));

從上面可以看出,使用轉換引擎可以輕松實現中文顯示,簡要步驟如下:

1. 修改main.cpp文件,將字體改為unifont

QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

qApp->setFont(font1);

2. 在想漢化的內的頭文件中加入QTextCodec指針變量和轉換函數QString mytr(char *)

#include <qtextcodec.h>

QTextCodec* gbk;

QString mytr(const char *);

3. 在想漢化的類的實現文件中,修改類構造函數,加入:

gbk=QTextCodec::codecForName(“GBK”);

4. 在想漢化的類的實現文件中,添加mytr函數代碼

QString Form1::mytr(const char* chars) {

return gbk->toUnicode(chars,strlen(chars));

}

5. 在想漢化的類的實現文件中,用“mytr”替換“tr”

注:如果將codec成員變量改成QTextCodec派生類變量,編譯將通不過,比如將QTextCodec* gbk;改成QGbkCodec* gbk;編譯將報告此處有語法錯誤。

下面是相似的用法:

1. 修改***.cpp文件,在頂部加入codec頭文件

#include <qgbkcodec.h>

2. 在***.h文件中,加入mytr()函數聲明

QString mytr(char* buffer,int size);

3. 在***.cpp文件中,加入mytr()定義

QString mytr(char* buffer,int size) {

QGbkCodec* gbk=QTextCodec::codeForName(“GBK”);

return gbk->toUnicode(buffer,size);

}

4. 在需要顯示中文的地方,使用mytr函數即可

5. 修改main.cpp文件,將字體改為unifont

QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

qApp->setFont(font1);

備注1:在翻譯或轉換之前必須將Unicode字體調入,否則顯示不出中文,網上相關文章並未提及這一點,如果不顯式裝載該字體,系統默認的是Latin1,於是漢字顯不出來。

備注2:在編譯qt/embedded之前,必須修改qconfig-qpe.h配置文件的內容,將與TextCodec相關的宏定義給去掉,否則QTextCodec::codecForName(“GBK”)將返回NULL指針。

備注3:使用findtr命令時可同時查找多個文件的tr(),並將查找結果都放入一個文件內,源文件以空格隔開即可,另外,生成的.po和.qm文件的文件名最好與工程文件名相同!

備注4:如果要顯示繁體中文,則需要使用QTextCodec::codecForName(“big5”)。獲取本地的使用語言,用QTextCodec::locale(),它返回Qstring變量,通常如果是中文本地的話,通常其值為zh_CN.GB2312和zh_TW.Big5,根據這個返回字符串,可以加載相應的codec。如果程序只支持一種編碼,也可以直接把整個應用程序的編碼設置為一個默認的編碼標准,比如系統只需要顯示中文和英文,則可以直接設置應用程序的默認編碼標准是GBK,如下使用方法:

qApp->setDefaultCodec( QTextCodec::codecForName("GBK") );

QLabel *label = new QLabel( tr("中文標簽") );

備注5:如果使用本地的字符轉換器,可以使用Qstring的靜態函數Qstring::fromLocal8Bit(char* buffer,int size),將本地字符串轉換成UNICODE字符串,不過要設置好LANGUAGE環境變量。

【QTOpia中文化 】

1) findtr 文件名 > xxx.po

2) 編輯xxx.po文件

3) msg2qm –scope zh_CN.GB2312 xxx.po xxx.qm

4) 拷貝可執行文件到QPEDIR/bin目錄

5) 拷貝xxx.po和xxx.qm文件到QPEDIR/i18n/zh_CN目錄

6) 進入QPEDIR/apps/Applications目錄創建一新.desktop文件

7) iconv –f utf8 –t GB18030 xxx.desktop > xxx1.desktop

8) 編輯xxx1.desktop文件,主要是修改Exec、Icon、Name和Name[zh_CN]四項

9) iconv –f GB18030 –t utf8 xxx1.desktop > xxx.desktop

10) rm –f xxx1.desktop

11) qvfb –depth 16 &

12) cd $QPEDIR/bin

13) ./qpe

備注1:如果你的系統中有多個qtopia版本,要特別注意QTDIR、QPEDIR、LD_LIBRARY_PATH環境變量

 

備注2:可按照此方法漢化qtopia自帶的應用程序

備注3:po文件是中間文件,程序真正需要的是qm文件。iconv是系統自帶的內碼轉換工具,它能將utf8編碼的文件轉換成gb18030編碼的文件,反之也能,轉換這一步必不可少,因為desktop文件缺省是utf8編碼的,而我們的redhat linux 7。3中文操作系統用的卻是gb18030,所以在編輯器打開前需轉換。

 

Linux教程-Linux下應用程序開發:QT國際化編程

Qt 目前的版本(2.2.4)對國際化的支持已經相當完善。 在文本顯示上,Qt 使用了Unicode 作為內部編碼,可以同時支持多種編碼。 為 Qt 增加一種編碼的支持也比較方便,只要 增加該編碼和Unicode的轉換編碼便可以了。 Qt 目前支持ISO標准編碼ISO 8859-1, ISO 8859-2,ISO 8859-3,ISO 8859-4,ISO 8859-5,ISO 8859-7,ISO 8859-9,和 ISO 8859-15(對於阿拉伯語和希伯來語的支持正在開發之中),中文GBK/Big5,日文 eucJP/JIS/ShiftJIS,韓文eucKR,俄文KOI8-R。 當然也可以直接使用UTF8編碼。
  
  Qt 使用了自己定義的Locale機制,在編碼支持和信息文件(Message File)的翻譯上彌補了目前Unix上所普遍采用Locale和gettext的不足之處。 Qt 的這種機制可以使 Qt 的同一組件(QWidget)上同時顯示不同編碼的文本。 比如,Qt 的標簽上可以同時使用中文簡體 和中文繁體文本。
  
  在文本輸入上,Qt 采用了XIM(X Input Method)標准協議,可以直接使用XIM輸入服務器。由於目前的絕大多數輸入服務器都是針對單一語言的,所以在 Qt 的標准輸入組件( QLineEdit,QMultiLineEdit)中的輸入受到單一編碼的限制,Qt 還不支持動態切換編碼 輸入的支持,這是它的不足之處。
  
   1. Qt 的文本顯示
  使用 Qt 編寫國際化的程序,最好不要在程序中直接使用特殊編碼的文本。 比如要 編寫一中文界面的 Qt 程序,應該在程序中使用英文,程序編寫完成后,把文本提取 出來翻譯。 這樣,程序還可以根據Locale的不同,支持多種語言。 下面介紹如何在 Qt 程序中標注字符串,如何提取並翻譯文本。
  
  像普通的國際化過程一樣,Qt 使用了類似GNU gettext一樣的函數 QObject::tr(),它 用於從Qt的信息文件 .qm 中取出信息,這些信息是經過 Qt 的工具處理的。 Qt在處理 編碼時還使用了 QTranslator 類,可用於指定整個應用軟件的 的信息文件。
  
  下面是一段使用了 QObject::tr()的代碼,它建立了一個彈出菜單,菜單項是"Quit", 它被放置在菜單條上,在菜單條上顯示的是標簽"File"。
  
  QPopupMenu* popup;
  popup = new QPopupMenu( this );
  popup->insertItem( tr("&Quit"),qApp,SLOT(quit()) );
  menubar->insertItem( tr("&File"),popup );
  
  對於絕大多數情況,可以用上述方法處理。不過有時在定義某些變量中使用的字符 串,不能使用上述方法,但是為了讓Qt提取並翻譯該字符串,必須用某種方法標志出 來。Qt 定義了 QT_TR_NOOP() 和 QT_TRANSLATE_NOOP() 來標志它們。前者用於單個字符串,后者用於多個字符串。比如,
  
  static const char* strings = {
  QT_TR_NOOP( "Hello" ),
  QT_TR_NOOP( "World" )
  };
  
  有時需要使用printf/sprintf之類的函數動態生成字符串,比如,
  
  QStings s;
  s.sprintf( "Button %d",i );
  but->setText( s );
  
  對這種使用方式的國際化是使用 arg() 函數。
  
  QString s = tr( "Button %1" ).arg(i);
  but->setText( s );
  
  提取上述信息的方法是使用 Qt 提供的工具 findtr 命令:
  
  findtr .cpp > i18n.po
  
  它類似於GNU的 xgettext,上述文件的提取信息文件內包含,
  
  ....
  "Content-Type: text/plain; charset=iso-8859-1\n"
  
  #: i18n.cpp:34
  msgid "ExampleWidget::&File"
  msgstr ""
  ...
  
  接下來是文本翻譯過程。 在Qt中翻譯信息文件時應該注意以下事項: (1) 提取的信息文件的編碼是iso-8859-1,在翻譯成某種語言(編碼)時應該 注意改動它的 字符集,比如對中文GB2312和Big5編碼,應該是, "Content-Type: text/plain; charset=gb2312\n"或者"Content-Type: text/plain; charset=big5\n"。 (2) 提取的信息有一個范圍,比如上面的文件指定的范圍是 ExampleWidget, 在翻譯 前應該把它去掉,變成 msgid "::&File"。(3) 被翻譯的字符串可能含有加速鍵符號,如 "&File"中的"F",如果翻譯成中文最好保留該信息,它可以翻譯成 "文件(&F)"。
  
  對於翻譯后的文件(比如上面的翻譯文件存為 i18n_gb.po),必須使用 Qt 提供的 工具 msg2qm 把它轉換為 .qm 文件才能使用,
  
  > msg2qm i18n_gb.po i18n_gb.qm
  
  它類似於GNU的 msgfmt 命令。翻譯后的文件可以用Qt程序直接調用。
  
  QTranslator *translator = new QTranslator(0);
  translator->load("i18n_gb.qm",".");
  qApp->installTranslator(translator);
  
  此外,Qt 還提供了類似於 msgmerge 的工具 mergetr,它用於把新提取的信息 文件和已經翻譯過的信息文件融合起來,在此不再贅述。
  
  在 Qt 中也可以直接使用 QTextCodec 來轉換字符串的編碼,這為在Qt下開發純 中文軟件帶來了便利條件,不過這種方法不符和國際化/本地化的習慣,
  
  char *string = "中文和English混和字符串!"
  QTextCodec* gbk_codec = QTextCodec::codecByName("GBK");
  QString gbk_string = codec->toUnicode(string);
  QLabel *label = new QLabel(gbk_string);
  
  如果使程序只支持一種編碼,也可以直接把整個應用程序的編碼設置為GBK編碼, 然后在字符串之前 加tr(QObject::tr),
  
  qApp->setDefaultCodec( QTextCodec::codecForName("GBK") );
  QLabel *label = new QLabel( tr("中文標簽") );
  
  如果使Qt根據Locale的環境變量取得字符集,可以使用
  
  QString::fromLocal8Bit(str)。
  
  本節的例子請參見 qt-i18n-example.tar.gz
  
   2. Qt 的文本輸入
  在輸入方面,Qt 的輸入條(QLineEdit)和編輯區(QMultiLineEdit)都支持 XIM,只要配合相應的輸入服務器,便可以輸入中文/日文/韓文。目前有許多支持XIM的軟件,比如 中文: Chinput/xcin/rfinput/q9,日文: kinput2/skkinput,韓文: ami/hanIM。
  
  Qt程序的缺省輸入風格是OverTheSpot風格,它也支持 OffTheSpot風格和 Root風格。 用戶可以在起動程序時在命令行指定輸入風格,比如對程序app,
  
  
  ./app -inputstyle overthespot  #缺省風格,光標跟隨
  ./app -inputstyle offthespot
  ./app -inputstyle root
  
  經過 MiziLinux 補丁的Qt-2.2.0 支持 OnTheSpot 輸入風格,並且把它作為 缺省的輸 入風格。請參見 http://www.mizi.com/ko/kde/doc/onthespot/onthespot.html。
  
  Qt 中的任何一個 Widget 都可以接受輸入,只要它可以有鍵盤聚焦(Keyboard Focus)。所以對特殊 Widget 的輸入處理只需要截獲鍵盤輸入,獲取從XIM服務器 來的字符串。 對於OverTheSport風格的支持,刷新XIM輸入服務器的位置即可。
  
   3. Qt 的打印
  在打印方面,XWindow下的 Qt 生成PostScript並使用lpr打印。 它含有QPrinter類, 可以方便地支持輸出頁面的控制。 對於中文打印,必須修正PostScript文件的輸出 部分。 

 

http://blog.csdn.net/liuguangzhou123/article/details/7474102


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM