环境
系统:Windows10 64位 家庭版
Qt版本:5.6.0 msvc2013 32位
编译器:Visual Studio 2013 专业版
目的
在Qt程序中切换语言时,各个窗口中的控件可以实时对字符串进行翻译、显示。
原理
1.捕捉Qt事件中的语言变化事件;
2.重新设置所有字符串。
示例步骤
1.新建一个Qt Widgets工程,这里我取名为MultiLanguage,如下图所示:
2.添加一个基类为QWidget的类(这里我取名为BaseMutliLanguage),这个类的作用是捕获语言切换事件和声明重新设置字符串的虚函数,关键代码如下:
BaseMultiLangauage.h 文件
#ifndef BASEMULTILANGAUAGE_H
#define BASEMULTILANGAUAGE_H
#include <QWidget>
class BaseMultiLangauage : public QWidget
{
Q_OBJECT
public:
explicit BaseMultiLangauage(QWidget *parent = 0);
protected:
void changeEvent(QEvent* event);
virtual void retranslateUi();
};
#endif // BASEMULTILANGAUAGE_H
BaseMultiLangauage.cpp文件
#include "BaseMultiLangauage.h"
#include <QEvent>
#include <QDebug>
BaseMultiLangauage::BaseMultiLangauage(QWidget *parent)
: QWidget(parent)
{
}
void BaseMultiLangauage::changeEvent(QEvent *event)
{
switch (event->type()) {
case QEvent::LanguageChange:
retranslateUi();
return;
break;
default:
break;
}
QWidget::changeEvent(event);
}
void BaseMultiLangauage::retranslateUi()
{
qDebug() << __FUNCTION__ << "This is BaseMultiLanguage";
}
3.添加基类为BaseMultiLangauage的派生类(这里我取名为TestWidget,并添加QLabel用来显示信息),然后重新实现retranslateUi()函数,关键代码如下:
TestWidget.h文件
#ifndef TESTWIDGET_H
#define TESTWIDGET_H
#include "BaseMultiLangauage.h"
class QLabel;
class TestWidget : public BaseMultiLangauage
{
//这个宏要特别注意,如果没有添加这个宏,程序无法识别tr
//会导致可以成功生成.qm文件,但是重新设置字符串不翻译的现象
Q_OBJECT
public:
explicit TestWidget(QWidget *parent = 0);
protected:
void retranslateUi();
private:
QLabel* m_pLblDisplay = Q_NULLPTR;
};
#endif // TESTWIDGET_H
TestWidget.cpp文件
#include "TestWidget.h"
#include <QLabel>
#include <QDebug>
#include <QEvent>
#include <QApplication>
TestWidget::TestWidget(QWidget *parent)
: BaseMultiLangauage(parent)
{
this->resize(200, 30);
m_pLblDisplay = new QLabel(this);
m_pLblDisplay->resize(200, 30);
retranslateUi();
}
void TestWidget::retranslateUi()
{
m_pLblDisplay->setText(tr("What language is this?")); //这里一定要用tr包起来,不然Qt语言家无法识别
}
4.参考 https://blog.youkuaiyun.com/chase_hung/article/details/90106533 生成.qm文件并添加到资源文件中,如下图所示:
5.在MultiLanguage类中添加一个QPushButton作为切换语言的入口,同时生成一个TestWidget对象用来观察,关键代码如下:
void MultiLanguage::initUi()
{
m_pTranslator = new QTranslator(this);
m_pBtnChangeLanguage = new QPushButton(this);
m_pBtnChangeLanguage->resize(150, 30);
m_pBtnChangeLanguage->setText(tr("Change Language"));
connect(m_pBtnChangeLanguage, &QPushButton::clicked, this, [=]{
m_bDisplayChinese = !m_bDisplayChinese;
if (m_bDisplayChinese)
{
m_pTranslator->load(":/language/langChinese.qm");
} else {
m_pTranslator->load(":/language/langEnglish.qm");
}
qApp->installTranslator(m_pTranslator);
});
m_pTestWidget = new TestWidget(this);
m_pTestWidget->move(0, m_pBtnChangeLanguage->y() + m_pBtnChangeLanguage->height());
}
6.程序初始化后的效果如下图:
单击"Change Language"按钮后效果如下图:
说明:
- TestWidget继承自BaseMultiLangauage且在retranslateUi()函数中重新设置了QLabel的显示文本,所以成功翻译;
- 按钮所在界面没有继承自BaseMultiLangauage且重写retranslateUi()函数,所以这里没有翻译,如果要翻译的话,在按钮槽函数的最后重新设置一下按钮的文本就可以翻译;
- 后续窗口只要继承自BaseMultiLangauage且在retranslateUi()函数中重新设置所有控件的显示文本就可以实现所有窗口实时翻译;
- 如果有某些共通的文本要翻译(比如鼠标悬停在任务栏图标上时的窗口标题),可以在基类BaseMultiLangauage的retranslateUi()函数实现,然后所有派生类中的retranslateUi()函数的最后加上BaseMultiLangauage::retranslateUi(); ;
- Q_OBJECT宏一定要记得加。