动态翻译combobox qml

时间:2018-11-13 09:24:24

标签: qt qml

我已使用本教程将翻译添加到我的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问题的答案,这确实很糟糕,但这也许是我的问题。

3 个答案:

答案 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
        }
    }