SYSZUXpinyin输入法完全是用qt搭建的,移植到arm平台后,可以弹出软键盘,本人已成功。移植过程可以参考http://blog.chinaunix.net/uid-24219701-id-3077611.html这里,等有时间洒家写个移植的小细节。这里主要讲,移植后整个程序的文本、字符编码方式怎么调整才能避免乱码。
我的环境是在Fedora14下,默认的编码方式是UTF-8,在未移植SYSZUX拼音之前,main函数里设置:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); //UTF-8
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
如此设置,UDP的接收端和发送端都可以正常显示中文。但SYSZUXpinyin采用的是GB2312方式,在主函数里必须设置QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312")); 在弹出的软键盘里才能正常显示中文。值得交代的是,main函数里只需要加这一句就可以了,多加任何如QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));或者QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"))都会让软键盘显示异常!这块也是最纠结的地方.
主函数里设成GB2312后,除了按钮上的汉字可以正常显示外,其他的如标题等都不能正常显示了。因为我们的linux下qt默认的中文环境是UTF-8格式,要正常显示中文必须转化成UTF-8格式。解决方法是:在widget.h里,#include <QTextCodec>,然后定义:QTextCodec *tc; 在widget.cpp的构造函数里:tc = QTextCodec::codecForName("UTF-8"); 以后显示中文就用如:this->setWindowTitle(tc->toUnicode("Esto网络通讯模块----客户端"))来显示!
奇怪的是本地EditText是可以正常显示的,如ui->getTextEdit->insertPlainText( sendStr +"\n");操蛋就操蛋在发送端和接收端。在对端上中文都是乱码。我原以为tr设成GB2312后,对CStrings默认的也成了GB2312.既然发送端是GB2312,我曾实验发送端GB2312-----------接收端GB2312解析,显示出来还是乱码。将解析的GB2312再转成UTF-8还是乱码,郁闷我一个下午,几乎近于崩溃!后来我意识到,这个想当然cstrings的编码格式是错误的。
后来用QtCreator的帮助手册,问题出在udp的发送函数 在发送之前将QString转成QByteArray,
QString sendStr = ui->sendTextEdit->toPlainText();
QByteArray sendByteArray = sendStr.toAscii();
这里是通过.toAscii()方式转换的。转换时依据的编码方式就是setCodecForCStrings设的值,看下手册上咋说的:
QByteArray QString::toAscii () const
Returns an 8-bit representation of the string as a QByteArray.
If a codec has been set using QTextCodec::setCodecForCStrings(), it is used to convert Unicode to 8-bit char; otherwise this function does the same as toLatin1().
默认的是采用toLatin1()转换的,所以接受端无论按GB2312还是UTF-8怎么转都是乱码。而在主函数里又不能设定全局的setCodecForCStrings的编码方式。所以我最初尝试在send函数发送前,setCodecForCStrings()设成UTF-8,然后发送完后再将setCodecForCStrings()设成GB2312,发现只有第一次能发送中文,对端能正常显示。以后软键盘就乱码了。问题的根源在这里,SYSZUXpinyin的tr编码方式是GB2312,而setCodecForCStrings()这里应该是默认值,默认值多少呢?再看手册:
void QTextCodec::setCodecForCStrings ( QTextCodec * codec ) [static]
Sets the codec used by QString to convert to and from const char * and QByteArrays. If the codec is 0 (the default), QString assumes Latin-1.
默认的是Latin-1格式,也就是将codec设成0就恢复到默认状态了。用这个思路改,应该也能成功!
其实,问题的症结在toAscii()的时候依据的编码格式,能够在toAscii()之前,将QString转成UTF-8不就好了么。
将这句话QByteArray sendByteArray = sendStr.toAscii();改成QByteArray sendByteArray = sendStr.toUtf8().data();UDP的显示消息模块不变,依然用
QTextCodec *tutf=QTextCodec::codecForName("UTF-8");
QString dataStr =tutf->toUnicode(data);还用UTF-8来解析,这样就能正常接收消息并显示中文了!
我后来又实验了上面的思路,在执行QByteArray sendByteArray = sendStr.toAscii(); 这句话之前,将setCodecForCStrings通过QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));设为UTF-8格式,在UDP发送函数的末尾加上,QTextCodec::setCodecForCStrings(0);将编码方式设为0,也就是默认的Latin-1.格式,经过测试,一切正常!两种方法都可以。接收函数保持不变。
我将udp部分的send函数和receive函数贴下,大家看完整的可以看我以前的帖子:
void Widget::send()
{
autoScroll();
QString sendStr = ui->sendTextEdit->toPlainText();
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QByteArray sendByteArray = sendStr.toAscii();
// QByteArray sendByteArray = sendStr.toUtf8().data(); //为了配合SYSZUXpinyin输入法,这种方法也可以
QMessageBox box;
if(sendStr.length()==0)
{
box.setText(tc->toUnicode("请输入发送内容"));
box.exec();
}
else if(configFlag)
{
udpSocket1->writeDatagram(sendByteArray, sendByteArray.length(), *remoteHostAddr, 6665);
//本地发送信息再信息交互窗口的显示
QDateTime time;
QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
ui->getTextEdit->setTextColor(QColor("red"));
ui->getTextEdit->insertPlainText(tc->toUnicode("本机") + localIpStr + ": " + timeStr + "--UDP--\n");
ui->getTextEdit->setTextColor(QColor("black"));
ui->getTextEdit->insertPlainText( sendStr +"\n");
ui->sendTextEdit->clear(); //点击发送后,发送编辑框内清零
ui->sendTextEdit->setFocus(); //焦点停留在发送编辑框
autoScroll();
}
else if(!configFlag)
{
box.setText(tc->toUnicode("请您先点击确认按钮!"));
box.exec();
}
QTextCodec::setCodecForCStrings(0);//为了让移植的SYSZUXpin软键盘中文显示正常,必须让CStrings恢复到默认的Latin-1编码格式
}
void Widget::receive()
{
while(udpSocket1->hasPendingDatagrams())
{
autoScroll();
QTextCodec *tutf=QTextCodec::codecForName("UTF-8");
QDateTime time;
QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QByteArray data;
data.resize(udpSocket1->pendingDatagramSize());
udpSocket1->readDatagram(data.data(), data.size());
//QString dataStr = QString::fromUtf8(data.data()); //这样写也是正确的
QString dataStr =tutf->toUnicode(data);
ui->getTextEdit->setTextColor(QColor("red"));
ui->getTextEdit->insertPlainText(tc->toUnicode("远程") + remoteIpStr+": "+ timeStr +"--UDP--\n" );
ui->getTextEdit->setTextColor(QColor("black"));
ui->getTextEdit->insertPlainText(dataStr + "\n" );
autoScroll();
}
总结下:
1,SYSZUXpinyin官方只说是用GB2312编码,实际没有说全,他的tr要设成GB2312,而CStrings不用设,保留默认,其实是QString默认的Latin-1格式。而这个格式直接影响QString转QByteArray的编码格式,这个格式搞不对,在接收端就像没娘的熊瞎子,乱试就是显示不了正常的中文。
2,QString与QByteArray的转换
QString string;
QByteArray data;
data = string.toAscii(); //按照setCodecForCStrings()的格式进行转换
sendStr.toLatin1().data(); //如果转换格式未设置,则上面的转换等同于此,即按默认的Latin1格式转换
data = string.toUtf8().data(); //按UTF-8格式
QByteArray转QString:
QByteArray encodedString = "xxx";
QTextCodec *tc = QTextCodec::codecForName("UTF-8");
QString string = tc->toUnicode(encodedString);
3,其实现在我们再想想,如果UDP发送端对setCodecForCStrings不设UTF-8,
直接data = string.toAscii(); 让他按照默认的setCodecForCStrings()方式Latin-1进行转。
在接收方得到QByteArray之后,按照QTextCodec *tc = QTextCodec::codecForName("Latin1");
进行转换QString,得到Latin1编码格式的QString,再对QString的data数据进行UTF-8转换,
应该也能正常显示中文!
结论:
移植SYSZUXpinyin的注意了,为了让SUSZUXpinyin的软键盘正常拼出中文,
CStrings的编码格式一定要设成默认的Latin1格式,同时tr设成GB2312.
看来我们解决问题,一定要理清头绪,多看软件的英文参考文档,
从原理出发去解决,往往事半功倍!