前言
用户那给的协议是和QT相关的,并没有输出裸数据,而是用QT序列化之后输出的。
如果要访问他们的socket server, 得到数据后,要处理成裸数据才能用.
为了解决能用他们提供的协议数据,有下面2个方法:
- 使用相同版本的QT, 写个client, 得到数据后,将数据变成裸数据(基础数据类型 + struct)存起来,供自己的程序来取。
- 直接用其他语言(e.g. C/C++)访问QT版的socket server, 得到数据后,按照逆向的方法分析QT类型数据的内存布局,然后自己转成裸数据存起来。
我采用第一种方法来弄,最简单直接。
我要作的这个小client, 需要国际化。
因为我对QT不熟,客户将他们的qt版demo工程给了一个作参考。而且给了开发环境QT4.7.0的安装包。
我发现,他们的软件支持中英文,但是都是在程序中写死的。硬编码,维护肯定不方便啊
于是就想先看看国际化怎么作合适。
看到了参考资料:
https://blog.csdn.net/qq_35451572/article/details/79498037
但是资料版本的QT明显比4.7.0高,并没有找到他说的菜单来转语言文件。
但是lupdate.exe在QT安装目录中有。我用命令行转语言文件好使。
又找到个资料,这个使用命令行来干活的
https://blog.csdn.net/hebbely/article/details/69388763
试验
将工程编码页设置为UTF8
因为用lupdate来生成语言文件,是要求工程中的编码页为UTF8
然后重启QT,使编码页生效
编译工程文件,加入语言文件说明
要翻译的字符串必须用tr包裹
看了一眼工程,字符串已经都用tr包裹了。
// e.g.
ui->my_tip->setText(tr("prev"));//上一个
控件必须有可翻译的属性
添加QT控件后,默认就有可翻译的属性。
用lupdate转语言文件
将QT的bin目录加入PATH. 我这默认安装完QT4.7.0,qt工具的路径是 C:\Qt\2010.05\qt\bin
设置好环境变量后,新开一个cmd.
cd /d D:\ls\dev_tmp\test_qt
lupdate test_qt.pro
这时,可以看到工程目录下生成了中英文的语言文件,还挺大的。
打开ts文件,看看QT生成的语言文件是啥样子的:)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
<context>
<name>dlg_a</name>
<message>
<location filename="dlg_a.ui" line="78"/>
<source>对话框A</source>
<translation type="unfinished"></translation>
</message>
<message utf8="true">
<location filename="dlg_a.ui" line="100"/>
<source>状态A</source>
<translation type="unfinished"></translation>
</message>
<message utf8="true">
<location filename="dlg_a.ui" line="131"/>
<source>上一个</source>
<translation type="unfinished"></translation>
</message>
可以看出, QT是对.ui文件的控件定义行数那,指定了可替换的文本。
而且控件和父窗口都有对应关系。
用QT工具 Linguist.exe 编辑语言文件
Linguist.exe 是图形化工具,载入ts文件编辑保存。
这时,如果源工程编码时,不是UTF8编码,在Linguist.exe看到的源字符串就是乱码。
编辑完保存。这步,必须用Linguist.exe编辑保存完,才能用lrelease x.pro生成qm文件
生成qm文件
lrelease test.pro
qt自带例子中使用多语言的例子
用Source Insight, 将C:\Qt\2010.05\qt\examples包含进来,看哪里操作.qm"
LanguageChooser::LanguageChooser(QWidget *parent)
: QDialog(parent, Qt::WindowStaysOnTopHint)
{
groupBox = new QGroupBox("Languages");
QGridLayout *groupBoxLayout = new QGridLayout;
QStringList qmFiles = findQmFiles();
for (int i = 0; i < qmFiles.size(); ++i) {
QCheckBox *checkBox = new QCheckBox(languageName(qmFiles[i]));
qmFileForCheckBoxMap.insert(checkBox, qmFiles[i]);
connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled()));
groupBoxLayout->addWidget(checkBox, i / 2, i % 2);
}
groupBox->setLayout(groupBoxLayout);
buttonBox = new QDialogButtonBox;
showAllButton = buttonBox->addButton("Show All",
QDialogButtonBox::ActionRole);
hideAllButton = buttonBox->addButton("Hide All",
QDialogButtonBox::ActionRole);
connect(showAllButton, SIGNAL(clicked()), this, SLOT(showAll()));
connect(hideAllButton, SIGNAL(clicked()), this, SLOT(hideAll()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(groupBox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
#ifdef Q_WS_MAC
qt_mac_set_menubar_merge(false);
#endif
setWindowTitle("I18N");
}
void LanguageChooser::checkBoxToggled()
{
QCheckBox *checkBox = qobject_cast<QCheckBox *>(sender());
MainWindow *window = mainWindowForCheckBoxMap[checkBox];
if (!window) {
QTranslator translator;
translator.load(qmFileForCheckBoxMap[checkBox]); // step 1
qApp->installTranslator(&translator); // step 2
window = new MainWindow;
window->setPalette(colorForLanguage(checkBox->text()));
window->installEventFilter(this);
mainWindowForCheckBoxMap.insert(checkBox, window);
}
window->setVisible(checkBox->isChecked());
}
找到的资料上,在载入.qm语言文件后,还会去刷新UI, 比官方demo考虑的细致。也许是官方demo, 选择完语言后,才显示其他主UI, 所以不用去刷新UI.
等用到的时候再试试。