【QML】QML和C++在QMainWindow框架下接口(亲测原创非抄袭)

tech2023-06-16  97

也不知道是QML用的人少,还是抄博客成风,网上关于QML和C++交互的文章几乎千篇一律,而且基本都是不能用了。

比如这篇文章:https://blog.csdn.net/x356982611/article/details/53871748

连接 qml中函数与c++中信号:

Connections { //qml 连接 c++ 信号 target:interaction onConnectcppsignal: { label2.text=strMsg; } }

这种方法是真的厉害,也不知道博主抄的时候有没有自己试过,反正我是一直报错,找不到onConnectcppsignal。

(一)在QMainWindow框架下,C++调用QML显示界面

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函数,根本不需要额外声明。

最新回复(0)