在插槽中接收 C++ 对象
Receiving a C++ object in a slot
我想通过信号槽将 C++ 对象发送到 QML :
class TaskInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ taskName)
...
// constructors
public:
TaskInfo();
TaskInfo(QIODevice *in);
TaskInfo(TaskInfo &&taskInfo);
TaskInfo(const TaskInfo &taskInfo); // it's just copy all variable
...
}
我有一个 class 可以将 TaskInfo 对象发送到 QML:
class DLDataConverter : public QObject
{
Q_OBJECT
signals:
void taskAdded_testQML(const TaskInfo taskInfo);
void taskAdded_useQString(const QString taskInfo);
...
}
我也发出一个信号并在 QML 中接收它:
void DLDataConverter::addItem(const TaskInfo &taskInfo)
{
emit taskAdded_testQML(taskInfo);
emit taskAdded_useQString(taskInfo.getInfoToString());
}
QML代码:
Connections {
target: DLDataConverter
onTaskAdded_testQML: {
console.log(taskInfo);
}
onTaskAdded_useQString: {
console.log(taskInfo);
}
}
onTaskAdded_useQString 信号工作正常,但 onTaskAdded_testQML 打印 'undefined'.
我已经注册了这些类型:
qmlRegisterType<TaskInfo>("taskInfo", 1, 0, "TaskInfo");
qmlRegisterSingletonType<DLDataConverter>("Singleton.DLDataConverter", 1, 0, "DLDataConverter", dataObj);
我可以创建 TaskInfo
对象并且效果很好:
TaskInfo{
id: t
}
Connections {
target: DLDataConverter
onTaskAdded_testQML: {
console.log(t.name); // print default value, is "Noname"
console.log(taskInfo); // print 'undefined'
}
}
QML 通过将每个参数转换为 QVariant
并在可能的情况下转换为原生 JavaScript 值来使用来自 Qt 的数据。如果不能转成JS,你还可以用JS复制传过去,但是你就不能用了。在不扩展QVariant
的情况下,只有QObject*
可以在QVariant
中被持有,并且是JS线程,它的属性、槽和信号对JS是可见的。 class 派生自 QObject
的任何指向对象的指针都会被 QVariant
隐式转换为 QObject*
。所以你可以自由定义指向你的 class 的指针信号为:
class DLDataConverter : public QObject
{
Q_OBJECT
signals:
void taskAdded_testQML(TaskInfo *taskInfo);
void taskAdded_useQString(const QString taskInfo);
...
}
指针引入了对象生命周期的问题,所以你一定要多了解一下如何manage the ownership of objects。
如果您像这样在 Qml 中创建对象:
TaskInfo{
id: t
}
您创建了一个具有 parent
的对象,其生命周期决定了对象本身的生命周期。指针绑定到本地 QML 上下文中的名称 t
。
我想通过信号槽将 C++ 对象发送到 QML :
class TaskInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ taskName)
...
// constructors
public:
TaskInfo();
TaskInfo(QIODevice *in);
TaskInfo(TaskInfo &&taskInfo);
TaskInfo(const TaskInfo &taskInfo); // it's just copy all variable
...
}
我有一个 class 可以将 TaskInfo 对象发送到 QML:
class DLDataConverter : public QObject
{
Q_OBJECT
signals:
void taskAdded_testQML(const TaskInfo taskInfo);
void taskAdded_useQString(const QString taskInfo);
...
}
我也发出一个信号并在 QML 中接收它:
void DLDataConverter::addItem(const TaskInfo &taskInfo)
{
emit taskAdded_testQML(taskInfo);
emit taskAdded_useQString(taskInfo.getInfoToString());
}
QML代码:
Connections {
target: DLDataConverter
onTaskAdded_testQML: {
console.log(taskInfo);
}
onTaskAdded_useQString: {
console.log(taskInfo);
}
}
onTaskAdded_useQString 信号工作正常,但 onTaskAdded_testQML 打印 'undefined'.
我已经注册了这些类型:
qmlRegisterType<TaskInfo>("taskInfo", 1, 0, "TaskInfo");
qmlRegisterSingletonType<DLDataConverter>("Singleton.DLDataConverter", 1, 0, "DLDataConverter", dataObj);
我可以创建 TaskInfo
对象并且效果很好:
TaskInfo{
id: t
}
Connections {
target: DLDataConverter
onTaskAdded_testQML: {
console.log(t.name); // print default value, is "Noname"
console.log(taskInfo); // print 'undefined'
}
}
QML 通过将每个参数转换为 QVariant
并在可能的情况下转换为原生 JavaScript 值来使用来自 Qt 的数据。如果不能转成JS,你还可以用JS复制传过去,但是你就不能用了。在不扩展QVariant
的情况下,只有QObject*
可以在QVariant
中被持有,并且是JS线程,它的属性、槽和信号对JS是可见的。 class 派生自 QObject
的任何指向对象的指针都会被 QVariant
隐式转换为 QObject*
。所以你可以自由定义指向你的 class 的指针信号为:
class DLDataConverter : public QObject
{
Q_OBJECT
signals:
void taskAdded_testQML(TaskInfo *taskInfo);
void taskAdded_useQString(const QString taskInfo);
...
}
指针引入了对象生命周期的问题,所以你一定要多了解一下如何manage the ownership of objects。 如果您像这样在 Qml 中创建对象:
TaskInfo{
id: t
}
您创建了一个具有 parent
的对象,其生命周期决定了对象本身的生命周期。指针绑定到本地 QML 上下文中的名称 t
。