我有一个包含以下内容的 QML 文件:
Text {
id: testData
onTaskClicked:{
testData.text = task.name
}
}
关键是这个 taskClicked 信号。它由另一个小部件 (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 中注册。 view
是我的 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
始终为空(并且我收到关于不存在插槽的运行时警告)。
如果我尝试将 View (QListView)指针设置为 QML View 的上下文属性,它仍然不起作用。
在所有情况下,我也得到:
QML Connections: Cannot assign to non-existent property "onTaskClicked"
我在这里可能做错了什么?
编辑以澄清一些细节:HolidayTask
是一个自定义 QObject 子类,信号 taskClicked
是在 C++ 中定义的(在 QListView
子类中)
EDIT2:我们正在接近,但没有雪茄:
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(m_view, SIGNAL(taskClicked(HolidayTask* task), myElement, SIGNAL(taskClicked(HolidayTask* task)));
简而言之,您需要以这种方式触发 QML 信号处理程序,而不是通过 SLOT
。
另外,请注意您的连接语法已损坏,因为它缺少末尾的右括号。这需要修复。
我什至会考虑删除指针分配并为此使用基于值或引用的传递。
关于c++ - 从 C++ (Qt5) 向 QML 项目发送信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22953866/