问题
Just came across a weird behavior of Qt framework while invoking overloaded C++ methods from within Qml and trying to understand the reason behind it. Let's say I have a QList<QVariant>
-like class with the following methods:
...
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 somehow decides to invoke the void insert(int index, const QVariantList &items)
overload with items
argument set to a an empty null QVariant
QVariantList
instead of the void insert(int index, const QVariant &item)
overload with QString
wrapped in QVariant
.
Now if I change the order of declarations as follows, it works as expected:
Q_SLOT void insert(int index, const QVariantList &items);
Q_SLOT void insert(int index, const QVariant &item);
I could not find anything under Qt framework's documentation regarding the order of declarations and how it affects the way methods are resolved during invoke.
Can someone please explain? Thank you.
回答1:
This question is related to overloading in JavaScript. Once you get to known with it -- you understand reason of "weird behavior" of your code. Just take a look at Function overloading in Javascript - Best practices.
In few words -- I recommend you to do next: since you can operate QVariant
variables on both sides (QML and Qt/C++) -- pass variant as parameter, and process it on Qt/C++ side as you wish.
You can use something like this:
Your C++ class created and passed to QML (e.g. as 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;
}
Somewhere in your 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)
}
}
来源:https://stackoverflow.com/questions/28529776/qt-qml-and-method-overloads