从C(Qt5)向QML项发送信号

我有一个包含以下内容的QML文件:

Text {
    id: testData
    onTaskClicked:{
        testData.text = task.name
    }
}

捕获是这个任务点击信号.它由另一个小部件(C)发出,需要中继到QML.

这类似于this SO question,除了那里发布的解决方案不起作用(为什么写在下面).

C代码:

ctxt->setContextProperty(QLatin1Literal("holiday"), m_model);
ctxt->setContextProperty(QLatin1Literal("bgcolor"), color);

view->setResizeMode(QQuickView::SizeRootObjectToView);

auto mainPath = QStandardPaths::locate(QStandardPaths::DataLocation,
                                           QLatin1Literal("taskview.qml"));

view->setSource(QUrl::fromLocalFile(mainPath));

ctxt->setContextProperty(QLatin1Literal("viewer"), m_view);

m_view是一个QListView子类,它发出taskClicked(HolidayTask * task)信号(来自.h文件):

Q_SIGNALS:
    void taskClicked(HolidayTask* task);

color和m_model在QML中注册,并在别处使用.来自信号的对象已经在QML中注册.视图是我的QQuickView.

首先,我尝试了上述问题中提出的解决方案:

auto root = view->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData");

connect(m_view, SIGNAL(taskClicked(HolidayTask* task), myElement,
        SLOT(taskClicked(HolidayTask* task);

但是,myElement始终为null(我收到有关不存在的插槽的运行时警告).

如果我尝试将视图(QListView)指针设置为QML视图的上下文属性,它仍然不起作用.

在所有情况下,我也得到:

QML Connections: Cannot assign to non-existent property "onTaskClicked"

我可能在这里做错了什么?

编辑澄清一些细节:HolidayTask是一个自定义的QObject子类,信号taskClicked是在C中定义的(在QListView子类中)

编辑2:我们越来越近,但没有雪茄:

auto root = quickView->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData"));

connect(m_view, SIGNAL(taskClicked(HolidayTask*)),
        myElement, SIGNAL(taskClicked(HolidayTask* task)));

Text {
    id: testData
    objectName: "testData"
    signal taskClicked(HolidayTask task)
    onTaskClicked: {
        testData.text = task.name
        console.log("CLICk!")
    }
}

产量

QObject::connect: No such signal QQuickText_QML_0::taskClicked(HolidayTask* task) in /home/lb/Coding/cpp/holiday-planner/src/mainwindow.cpp:178
QObject::connect:  (receiver name: 'testData')

更多细节:HolidayTask,我的自定义QObject子类,在代码中注册为

qmlRegisterType<HolidayTask>("HolidayPlanner", 1, 0, "HolidayTask");

带有数据的最小QML:

 import QtQuick 2.0
 import QtQml 2.2

import HolidayPlanner 1.0

Rectangle {
    id: container
    objectName: "container"
    color: bgcolor


   Text {
        id: testData
        objectName: "testData"
        signal taskClicked(HolidayTask task)
        onTaskClicked: {
            testData.text = task.name
            console.log("CLICK")
        }
   }

}

EDIT3:最终的工作代码是(查看原因的答案)

 connect(m_view, SIGNAL(taskClicked(HolidayPlanner::HolidayTask*)),
        myElement, SIGNAL(taskClicked(HolidayPlanner::HolidayTask*)));

这只能通过使用具有完整名称空间的对象来实现.否则签名在QML中将不匹配.

解决方法:

However, myElement is always null (and I get a runtime warning about
a non existent slot).

您正在尝试基于id查找子项,而它基于objectName属性.您需要将objectName属性设置为实际找到它的所需.

此外,您似乎没有在QML文本项中声明信号.我不确定它是自定义C项还是内置项.遗憾的是,您还没有分享足够的代码来理解这一点.无论哪种方式,声明您的信号as per documentation.

因此,请尝试以下代码:

Text {
    id: testData
    objectName: "testData"
    // ^^^^^^^^^^^^^^^^^^^
    signal taskClicked (HolidayTask task)
    // ^^^^^^^^^^^^^^^^^^^
    onTaskClicked:{
        testData.text = task.name
    }
}

一旦完成,你几乎准备好了.您需要将HolidayTask注册到QML,并且还需要更改main.cpp中的connect语法,如下所示:

connect(m_view, SIGNAL(taskClicked(HolidayTask* task), myElement, SIGNAL(taskClicked(HolidayTask* task)));

简而言之,您需要以这种方式触发QML信号处理程序,而不是通过SLOT.

另请注意,您的连接语法已损坏,因为它缺少最后的右括号.这需要修复.

我甚至会考虑删除指针赋值并使用值或基于引用的传递.

上一篇:@PostContruct注解服务启动后运行方法


下一篇:@PostConstruct详解