我有一个自定义类,需要在其中保存新选择的语言并同时更改应用程序语言。一个基于QtCreator中StackView示例项目的示例:
//main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
qmlRegisterType<CustomClass>("io.qt.CustomClass", 1, 0, "CustomClass");
QTranslator translator;
translator.load(":/EN.qm");
app.installTranslator(&translator);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
//customclass.h
class CustomClass : public QObject
{
Q_OBJECT
public:
explicit CustomClass(QObject *parent = nullptr) : QObject(parent) {}
Q_INVOKABLE void change(){
QTranslator translator;
QApplication::removeTranslator(&translator);
translator.load(":/CZ.qm");
QApplication::installTranslator(&translator);
//QQmlApplicationEngine * engine = qobject_cast<QQmlApplicationEngine *>(qmlEngine(this));
QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
engine->retranslate();
}
};
//main.qml
...
CustomClass{id:test}
...
ItemDelegate {
text: qsTr("Page 1")
width: parent.width
onClicked: {
test.change()
drawer.close()
}
}...
//.pro file
QT += quick gui core
...
TRANSLATIONS = EN.ts CZ.ts
...
HEADERS += \
customclass.h
在此示例中,单击Page 1按钮应更改语言。
我的应用程序基于StackView,当我使用此代码调用该函数时,一切似乎都可以正常工作。字符串已翻译。但是,当我将一个新项目推入堆栈时(例如从菜单中打开一个新部分),那里的字符串以更改之前的原始语言返回。就像重新翻译只更改当前可见的字符串一样。
有人知道问题出在哪里吗?我怀疑引擎无法正确获得。这是一个自定义类,我需要先注册(qmlRegisterType)才能在qml中使用,但我不确定如何正确地将引擎添加到那里(因为在主函数中创建了引擎)。
答案 0 :(得分:2)
我遇到了同样的问题。我发现的解决方案是在创建QTranslator对象时使用new运算符。这将导致在堆内存而不是堆栈中创建对象。如果它在堆栈存储器中,则在函数完成后,QTranslator将被删除(至少,这就是我的理解。我相信具有更多C ++经验的人可能会更好地解释它)。
因此,您的自定义类代码将如下所示:
//customclass.h
class CustomClass : public QObject
{
Q_OBJECT
public:
explicit CustomClass(QObject *parent = nullptr) : QObject(parent) {}
Q_INVOKABLE void change(){
QTranslator *translator = new QTranslator(qApp);
if (m_previousTranslator) {
QApplication::removeTranslator(m_previousTranslator);
m_previousTranslator->deleteLater();
m_previousTranslator = nullptr;
}
translator->load(":/CZ.qm");
m_previousTranslator = translator;
QApplication::installTranslator(translator);
QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
engine->retranslate();
}
private:
QTranslator *m_previousTranslator = nullptr;
};
请注意,我添加了一个私有变量m_previousTranslator
来进行一些内存管理。我尚未测试此示例代码,但我在项目中使用了非常相似的代码,并且可以正常工作
答案 1 :(得分:0)
我使用了一个肮脏的把戏来实现整个应用程序的重新翻译,而无需在类中使用引擎。这不是完美的,但可以。我在main中添加了一个循环,如下所示:
int returnValue = 0;
do
{
QApplication app(argc, argv);
QTranslator translator;
translator.load(":/translation/"+langString+".qm"); //langString might be the "CZ" as in the question example
app.installTranslator(&translator);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/src/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
returnValue = app.exec();
langString = settings.value("language").toString();
}
while(returnValue == TRANSLATION_RESTART);
return returnValue;
因此在我的自定义类中,我只需使用以下命令退出应用程序:
qApp->exit(TRANSLATION_RESTART);
我还保存了langString
值。这样,应用程序基本上会以新语言重新启动。