2015-02-15 4 views
9

Просто наткнулся на странное поведение Qt-фреймворка, вызывая перегруженные методы C++ из Qml и пытаясь понять причину этого. Скажем, у меня есть QList<QVariant> -как класс со следующими методами:Qt/Qml и перегрузки методов

... 
Q_SLOT void append(const QVariant &item); 
Q_SLOT void append(const QVariantList &items); 
Q_SLOT void insert(int index, const QVariant &item); 
Q_SLOT void insert(int index, const QVariantList &items); 
... 

QML:

onclicked: { 
    var itemCount = myListObject.size(); 
    myListObject.insert(itemCount, "Item " + (itemCount + 1)); 
} 

Qt как-то решает вызвать перегрузку void insert(int index, const QVariantList &items) с items аргументом, равным null QVariant пустой QVariantList вместо void insert(int index, const QVariant &item) перегрузка с QString, завернутая в QVariant.

Теперь, если изменить порядок заявлений следующим образом, она работает, как ожидалось:

Q_SLOT void insert(int index, const QVariantList &items); 
Q_SLOT void insert(int index, const QVariant &item); 

Я не мог найти что-либо по документации Qt фреймворки о порядке заявлений и как это влияет на то методу разрешенные во время вызова.

Может кто-нибудь объяснить это? Спасибо.

ответ

3

Этот вопрос связан с перегрузкой в ​​JavaScript. Как только вы узнаете об этом - вы понимаете причину «странное поведение» вашего кода. Просто взгляните на Function overloading in Javascript - Best practices.

В нескольких словах - я рекомендую вам сделать следующее: поскольку вы можете использовать переменные QVariant с обеих сторон (QML и Qt/C++) - передать вариант как параметр и обработать его на стороне Qt/C++, как вы пожелаете ,

Вы можете использовать что-то вроде этого:

Ваш C++ класс создан и передан QML (например, setContextProperty("TestObject", &tc)):

public slots: 
    Q_SLOT void insert(const int index, const QVariant &something) { 
     qDebug() << __FUNCTION__; 
     if (something.canConvert<QString>()) { 
      insertOne(index, something.toString()); 
     } else if (something.canConvert<QStringList>()) { 
      insertMany(index, something.toStringList()); 
     } 
    } 

private slots: 
    void insertOne(int index, const QString &item) { 
     qDebug() << __FUNCTION__ << index << item; 
    } 

    void insertMany(int index, const QStringList &items) { 
     qDebug() << __FUNCTION__ << index << items; 
    } 

Где-то в вашем QML:

Button { 
    anchors.centerIn: parent 
    text: "click me" 
    onClicked: { 
     // Next line will call insertOne 
     TestObject.insert(1, "Only one string") 
     // Next line will call insertMany 
     TestObject.insert(2, ["Lots", "of", "strings"]) 
     // Next line will call insertOne 
     TestObject.insert(3, "Item " + (3 + 1)) 
     // Next line will call insertOne with empty string 
     TestObject.insert(4, "") 
     // Next line will will warn about error on QML side: 
     // Error: Insufficient arguments 
     TestObject.insert(5) 
    } 
} 
+4

Можете ли вы упомянуть, что конкретно в системе перегрузки javascript вызывают это поведение? – UmNyobe

+1

спасибо за попытку..Я не искал решения ... решение простое - просто измените порядок объявлений ... Я пытался понять (для дальнейшего использования) о том, как и почему Qt решает вызвать неправильную перегрузку и просто полностью игнорирует типы данных. При изменении заказа, однако, у него нет проблемы с решением правильных сигнатур методов. С другой стороны, ваше решение ограничивает мой класс принятием только определенных типов данных. – gplusplus

+0

Действительно, это не отвечает на главный вопрос, т. Е. * Почему * происходит поведение. Глядя на это [old commit] (https://qt.gitorious.org/qt/tmartsums-qt/commit/1d7b672fd46abab51a0124ad19aad18e5d14f1a8), нет (очевидной) причины, по которым он не работает. Ошибка ?? – BaCaRoZzo

Смежные вопросы