我有一个包含以下内容的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中注册。 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
始终为null(我收到有关不存在的插槽的运行时警告)。
如果我尝试将视图(QListView)指针设置为QML视图的上下文属性,它仍然无法工作。
在所有情况下,我也得到:
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中将不匹配。
答案 0 :(得分:6)
但是,
myElement
始终为null(我收到运行时警告。) 一个不存在的插槽)。
您正在尝试根据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
。
另请注意,您的连接语法已损坏,因为它缺少最后的右括号。这需要修复。
我甚至会考虑删除指针赋值并使用值或基于引用的传递。
答案 1 :(得分:4)
您可以通过以下方式将信号从C ++连接到QML:
view->rootContext()->setContextProperty("testData",this);
QObject::connect(this,SIGNAL(taskClicked(HolidayTask* task)),(QObject *)view->rootObject(),SLOT(onTaskClicked(HolidayTask* task)));
当您的信号被命名为taskClicked
时,QML中的广告位应为onTaskClicked
。
同样在QML中,您应该通过以下方式命名对象testData
:
objectName: "testData"
答案 2 :(得分:1)
QML Connections: Cannot assign to non-existent property "onTaskClicked"
错误告诉您,您的Text
项目没有信号taskClicked
或属性onTaskClicked
!
您需要在文本项中声明一个插槽。为此,您只需声明一个函数:
Text {
id: testData
objectName: "testData" // as Laszlo said
function onTaskClicked( task ) {
testData.text = task.name;
}
}
但由于您创建的是SLOT( onTaskClicked(QVariant) )
而不是SLOT(taskClicked(HolidayTask*))
,因此也无效。要与QML交换数据,您需要将信号更改为SIGNAL(taskClicked(QVariant))
:
Q_SIGNALS:
void taskClicked(QVariant task);
然后发出:
emit taskClicked( QVariant::fromValue( task ) );
请注意,为了能够使用HolidayTask
,必须是QObject
注册的qmlRegisterType
。
您也可以simply call that qml function。
如果您无法使用QVariant,您可以在Text对象中声明一个信号:
Text {
id: testData
objectName: "testData" // as Laszlo said
signal taskClicked ( HolidayTask task )
onTaskClicked: {
testData.text = task.name;
}
}
然后从C ++ SIGNAL连接到qml SIGNAL:
auto root = view->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData");
connect(m_view, SIGNAL(taskClicked(HolidayTask*), myElement,
SIGNAL(taskClicked(HolidayTask*));