Get signal from qml into c++ class in Qt
我试图弄清楚如何从QML代码中获取信号并将其连接到C ++类中的插槽。
我从此答案和屏幕上显示的控件中获取代码,但无法获取信号。
以下是相关代码:
test.qml:
1 2 3 4 5 6 7 8 9 | import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 Switch{ id: swt; checked:true; onCheckedChanged: swt.qmlSignal(); } |
menu.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Menu::Menu(QWidget *parent) : QWidget(parent), ui(new Ui::Menu) { ui->setupUi(this); QQuickView *view = new QQuickView(); QWidget *container = QWidget::createWindowContainer(view, this); container->setMaximumSize(50, 20); QObject::connect(container, SIGNAL(qmlSignal()), this, SLOT(receiveFromQml())); view->setSource(QUrl("qrc:/test.qml")); ui->verticalLayout->addWidget(container); } void Menu::receiveFromQml() { qDebug() <<"Called the C++ slot with message:" ; } |
我在这里查看了示例,但无法使其正常工作。
这是我得到的错误:
qrc:/test.qml:10: TypeError: Property 'qmlSignal' of object Switch_QMLTYPE_4(0x291ac70) is not a function
简单,将其标记为插槽
似乎您有一个C ++对象,您需要调用一个插槽,因此将该函数标记为
1 2 3 4 5 6 | // Seems Switch is a QML Item Switch{ id: swt; checked:true; onCheckedChanged: myCppObj.slot(); // calls the object's slot } |
还有其他方法可以执行此操作,但这似乎可以解决您的问题。如果没有,请详细说明,我们将对其进行完善。
您无法在qml中创建其他信号,但可以使用对象的标准属性。
1 2 3 4 5 6 7 8 | import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 Switch{ id: swt; checked:true; } |
C ++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class MyHandler : public QObject { Q_OBJECT public: MyHandler( const QObject& object, const QQmlProperty& qmlProperty ); private slots: void handleNotify(); private: const QQmlProperty& m_qmlProperty; }; MyHandler::MyHandler( const QObject& object, const QQmlProperty& qmlProperty ) : QObject(), m_qmlProperty( qmlProperty ) { static const QMetaMethod metaSlot = this->metaObject()->method( this->metaObject()->indexOfSlot("handleNotify" ) ); if( metaSlot.isValid() ) { const QMetaMethod metaQmlPropSignal = qmlProperty.property().notifySignal(); if( metaQmlPropSignal.isValid() ) QObject::connect( &object, metaQmlPropSignal, this, metaSlot ); } } MyHandler::handleNotify() { if( m_qmlProperty.isValid() ) { const int qmlPropertyValue = m_qmlProperty.read().value<bool>(); ... } } |
使用:
1 2 3 4 | QQuickView* view = ...; QObject* quickItem = view->rootObject(); const QQmlProperty* qmlProperty = new QQmlProperty( quickItem,"checked" ); MyHandler* myHandler = new MyHandler( *quickItem, *qmlProperty ); |
因此,当属性
附言您还可以将qml属性与信号连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class QmlPropertyWrapper : public QObject { Q_OBJECT public: QmlPropertyWrapper( const QObject& object, const QQmlProperty& qmlProperty ); signals: void triggered(); }; QmlPropertyWrapper::QmlPropertyWrapper( const QObject& object, const QQmlProperty& qmlProperty ) : QObject() { static const QMetaMethod metaSignal = QMetaMethod::fromSignal( &QmlPropertyWrapper::triggered ); if( metaSignal.isValid() ) { const QMetaMethod metaQmlPropSignal = qmlProperty.property().notifySignal(); if( metaQmlPropSignal.isValid() ) QObject::connect( &object, metaQmlPropSignal, this, metaSignal ); } } |
使用
1 2 3 4 5 6 7 8 9 10 11 12 | QQuickView* view = ...; QObject* quickItem = view->rootObject(); const QQmlProperty* qmlProperty = new QQmlProperty( quickItem,"checked" ); QmlPropertyWrapper* qmlPropertyWrapper = new QmlPropertyWrapper( *quickItem, *qmlProperty ); QObject::connect( qmlPropertyWrapper, &QmlPropertyWrapper::triggered, [ qmlProperty ]() { if( m_qmlProperty->isValid() ) { const int qmlPropertyValue = m_qmlProperty->read().value<bool>(); ... } } ); |
我希望您的示例足够了,并且切换项也是根源。通常可以这样解决:
1 2 3 4 5 6 7 8 9 10 | Switch { id: swt signal gmlSignal checked:true; onCheckedChanged: { qmlSignal(); } } |
有关详细信息的Qt文章。同样,您可以在需要时使用限定符
另外,C ++部分也需要修复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Menu::Menu(QWidget *parent) : QWidget(parent), ui(new Ui::Menu) { ui->setupUi(this); QQuickView *view = new QQuickView(); QWidget *container = QWidget::createWindowContainer(view, this); container->setMaximumSize(50, 20); view->setSource(QUrl("qrc:/test.qml")); ui->verticalLayout->addWidget(container); QObject::connect((QObject*)view->rootObject(), SIGNAL(qmlSignal()), this, SLOT(receiveFromQml())); } |
我通过查看发出类似信号的自己的代码进行了更改,但实际上并没有尝试,但是您需要连接到从QML