我已使用本教程将翻译添加到我的qt / qml应用程序中
https://retifrav.github.io/blog/2017/01/04/translating-qml-app/ https://github.com/retifrav/translating-qml
大多数情况下似乎运行良好,只是组合框的值无法通过动态转换得到更新。 我使用的是qt 5.11.2。
通过组合框,我的意思是:
ComboBox {
textRole: "text"
Layout.fillWidth: true
model: ListModel {
Component.onCompleted: {
append({text: qsTr("None")})
append({text: qsTr("Subpanel")})
append({text: qsTr("All")})
}
}
}
ComboBox {
textRole: "text"
Layout.fillWidth: true
model: ListModel {
ListElement{text: qsTr("None")}
ListElement{text: qsTr("Subpanel")}
ListElement{text: qsTr("All")}
}
}
它们都没有更新。 我进行了一些研究,并在错误报告中找到了这一点 https://bugreports.qt.io/browse/QTBUG-68350 这似乎在5.12上已得到解决,但是由于各种原因,我们需要保持相同的版本,有没有办法我可以对此版本进行修复? (5.11.2)
编辑:我找不到翻译comboBox的方法。还有另一种翻译方法吗?即使这意味着要打开该应用程序的新实例?有人可以指出我的链接吗?无法找到一种方法。
EDIT2:有没有一种方法可以强制用javascript更新组合框的模型?何时调用changeLanguage()方法?
注意:作为投诉,我正在寻找支持/社区来寻求Qt问题的答案,这确实很糟糕,但这也许是我的问题。
答案 0 :(得分:2)
一个选择是添加一个*
来进行翻译。我使自己成为基类,可以继承。这也为您提供了很大的灵活性,可以将选定的项目转换为一个值(在本示例中,我使用的是int,但您可以将其设置为任意值),该值连接到C ++后端(我使用QAbstracstListModel
例子)
<<编辑:请参见Felix的答案以更好地添加动态翻译>>
基本标头:
backend.selectedPanel
基本cpp:
class baseEnum : public QAbstractListModel
{
Q_OBJECT
public:
virtual int rowCount(const QModelIndex &parent) const = 0;
virtual QVariant data(const QModelIndex &index, int role) const = 0;
QHash<int, QByteArray> roleNames() const;
Q_INVOKABLE int getIndex(int value);
Q_INVOKABLE int getValue(int index);
}
派生的标头:
QHash<int, QByteArray> baseEnum::roleNames() const
{
QHash<int, QByteArray> result;
result.insert(Qt::DisplayRole, "text");
result.insert(Qt::UserRole + 1, "value");
return result;
}
int baseEnum::getIndex(int value)
{
for(int i=0;i<rowCount(QModelIndex());++i)
if(data(createIndex(i, 0, nullptr), Qt::UserRole + 1).toInt() == value)
return i;
return -1;
}
int baseEnum::getValue(int index)
{
return data(createIndex(index, 0, nullptr), Qt::UserRole + 1).toInt();
}
派生的cpp:
class FancyEnum : public baseEnum
{
Q_OBJECT
public:
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
};
在某处注册:
int FancyEnum::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid())
return 5;
return 0;
}
QVariant FancyEnum::data(const QModelIndex &index, int role) const
{
switch(index.row())
{
case 0: return role == Qt::DisplayRole ? QVariant(tr("None")) : QVariant(0);
case 1: return role == Qt::DisplayRole ? QVariant(tr("Subpanel")) : QVariant(1);
case 2: return role == Qt::DisplayRole ? QVariant(tr("All")) : QVariant(2);
}
return role == Qt::DisplayRole ? QVariant(QString("<%1>").arg(index.row())) : QVariant(0);
}
在QML中的用法:
qmlRegisterType<FancyEnum>("your.path.here", 1, 0, "FancyEnum");
答案 1 :(得分:2)
这是@Amfasis答案的补充。通过添加检测和响应重新翻译事件的功能,它扩展了非常有用的“ baseEnum”模型
为使GUI在重新翻译后实际检测到文本已更改,模型必须“通知” GUI数据已更改。但是,为此,模型必须知道何时更改数据。值得庆幸的是,Qt拥有LanguageChange事件。以下代码捕获该事件,并使用该事件将数据更改通知gui。
// in the header file:
class baseEnum : public QAbstractListModel
{
Q_OBJECT
public:
// ... all the stuff from before
bool event(QEvent *event);
};
// and in the cpp file:
bool baseEnum::event(QEvent *ev)
{
if(ev) {
switch(ev->type()) {
case QEvent::LanguageChange:
// notifiy models that the display data has changed for all rows
emit dataChanged(index(0),
index(rowCount(QModelIndex{}) - 1),
{Qt::DisplayRole});
break;
}
}
return QAbstractListModel::event(ev);
}
答案 2 :(得分:1)
不幸的是,我目前无法测试所有情况(并且我无法访问Qt 5.11.2),但是我认为这应该可行:
ComboBox {
textRole: "text"
Layout.fillWidth: true
displayText: qsTr(currentText)
model: ListModel {
ListElement{text: "None"}
ListElement{text: "Subpanel"}
ListElement{text: "All"}
}
delegate: Button {
width: ListView.view.width
text: qsTr(model.text)
}
}
或者,另一种方法是在更改语言时重新创建模型:
ComboBox {
id: combobox
textRole: "text"
Layout.fillWidth: true
model: ListModel {
dynamicRoles: true
}
Component.onCompleted: {
reload()
}
Connections {
target: trans // this is a translator from a git project you are referring to
onLanguageChanged: {
combobox.reload()
}
}
function reload() {
var i = combobox.currentIndex
combobox.model = [
{text: qsTr("None")},
{text: qsTr("Subpanel")},
{text: qsTr("All")}
]
combobox.currentIndex = i
}
}