也不知道是QML用的人少,还是抄博客成风,网上关于QML和C++交互的文章几乎千篇一律,而且基本都是不能用了。
比如这篇文章:https://blog.csdn.net/x356982611/article/details/53871748
连接 qml中函数与c++中信号:
Connections { //qml 连接 c++ 信号 target:interaction onConnectcppsignal: { label2.text=strMsg; } }这种方法是真的厉害,也不知道博主抄的时候有没有自己试过,反正我是一直报错,找不到onConnectcppsignal。
1-我是通过创建一个 QQuickWidget *m_quickWidget 实现的:
QQuickWidget *m_quickWidget=new QQuickWidget(); QUrl source("qrc:/Screen_QML_Main.qml"); m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView ); m_quickWidget->setSource(source);2-另外还有一种方式是QQmlComponent+QQmlEngine
QQmlEngine engine; QQmlComponent component(&engine, "MyItem.qml"); QObject *object = component.create();但第二种方法是单独把QML显示出来,目前还未试过,应该是出现QMainWindow和QML两个窗口。
1-在QML中用QML/JS调用C++
(1.1)声明的时候前面加上:Q_INVOKABLE
Q_INVOKABLE int qml_getRecordVal_toint16(int i_dec);或者直接声明为
public slots:
因为slots和signals是经过QT特殊处理的,QML可以直接调用,否则普通函数都是向QML屏蔽的。
(1.2)然后绑定到QML
在qmainwindows的构造函数里:
m_quickWidget->rootContext()->setContextProperty("sql_mcDefine", sql_mcDefine);上述语句是把另一个类对象绑定进去(1.1)里面声明就是在 Sql_MCDefine 这个类里面声明的。如果你想在qmainwindows里面声明,就把qmainwindows传进去
m_quickWidget->rootContext()->setContextProperty("qmainwindows", this);(1.3)在QML里面用双引号里面的关键字调用
sql_mcRecorder.qml_getRecordVal_toint16(2);其实绑定之后相当于 Screen_QML_Main.qml 根目录下多了一个 sql_mcDefine 的 property。
2-在qmainwindows中用C++调用QML/JS
(2.1)使用 QMetaObject
QMetaObject::invokeMethod((QObject *)m_quickWidget->rootObject(),"recall");其中recall就是QML里面自定义的一个自定义的JS函数。
m_quickWidget->rootObject()返回一个QQuickItem,就是指向了 Screen_QML_Main.qml 根目录。不过不能直接用,要强制转化为(QObject *)。 千万要跟 rootContext 区分,rootContext 返回的不是指向 Screen_QML_Main.qml 根目录,找不到 recall函数。
1-QML穿信号到C++
参考:https://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html#accessing-loaded-qml-objects-by-object-name
(1.1)在QML定义信号
// MyItem.qml import QtQuick 2.0 Item { id: item width: 100; height: 100 signal qmlSignal(anObject: Item) MouseArea { anchors.fill: parent onClicked: item.qmlSignal(item) } }(1.2)在C++进行connect
class MyClass : public QObject { Q_OBJECT public slots: void cppSlot(QQuickItem *item) { qDebug() << "Called the C++ slot with item:" << item; qDebug() << "Item dimensions:" << item->width() << item->height(); } }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view(QUrl::fromLocalFile("MyItem.qml")); QObject *item = view.rootObject(); MyClass myClass; QObject::connect(item, SIGNAL(qmlSignal(QVariant)), &myClass, SLOT(cppSlot(QVariant))); view.show(); return app.exec(); }2-QML发,C++收
这个可以说是找遍全网没找到,找到的都是抄来抄去的错方法。
(2.1)在已经和QML绑定的C++类(绑定就是(二)(1.2)所述)里面声明一个信号
signals: void sn_sqlWriteFinish();就是普通的qt信号,平平无奇
(2.2)依然是在C++中进行connect
m_quickWidget->rootContext()->connect(sql_mcRecorder, SIGNAL(sn_sqlWriteFinish()), (QObject *)m_quickWidget->rootObject(), SLOT(recall()));其中一些重要的地方见(二)(2.1),QML的槽函数就是普通的JS函数,根本不需要额外声明。