从C ++(Qt5)向QML项目发送信号 [英] Sending a signal to a QML item from C++ (Qt5)

查看:70
本文介绍了从C ++(Qt5)向QML项目发送信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a QML file containing this:

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

要抓住的就是这个taskClicked信号.它是由另一个小部件(C ++)发出的,需要中继到QML.

The catch is this taskClicked signal. It is emitted by another widget (C++) and needs to be relayed to QML.

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

This is similar to this SO question, except that the solution posted there doesn't work (why is written below).

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文件):

m_view is a QListView subclass that emits the taskClicked(HolidayTask* task) signal (from the .h file):

Q_SIGNALS:
    void taskClicked(HolidayTask* task);

color m_model 已在QML中注册,并在其他地方使用.信号中的对象已在QML中注册. view 是我的 QQuickView .

color and m_model are registered in QML and are used elsewhere. The object from the signal is already registered in QML. view is my QQuickView.

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

First I tried the solution presented in the question above:

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(并且我收到有关不存在的插槽的运行时警告).

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

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

If I try to set the view (the QListView) pointer as a context property of the QML view, it still doesn't work.

在所有情况下,我都会得到:

In all cases, I get also:

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

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

What could I possibly be doing wrong here?

编辑以阐明一些细节: HolidayTask 是一个自定义QObject子类,信号 taskClicked 是用C ++定义的(在 QListView 子类中))

EDIT to clarify some details: HolidayTask is a custom QObject subclass, and the signal taskClicked is defined in C++ (in a QListView subclass)

我们越来越近了,但是没有雪茄:

We're getting close, but no cigar:

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')

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

More details: HolidayTask, my custom QObject subclass, is registered in the code as

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

带有数据的最小QML:

Minimal QML with the data:

 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")
        }
   }

}

最终有效的代码是(请参阅有关原因的答案)

The final, working code is (see answers on why)

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

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

This worked only through the use of objects with full namespaces. Otherwise the signature will not match in QML.

推荐答案

但是, myElement 始终为null(并且我收到有关以下内容的运行时警告:一个不存在的插槽).

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

您试图基于id查找子项,而它是基于objectName属性的.您需要将objectName属性设置为所需的值才能真正找到它.

You are trying to find the child based on id, whereas it is based on the objectName property. You would need to set the objectName property to the desired to actually find it.

此外,您似乎没有在QML Text项目中声明信号.我不确定这是自定义C ++项还是内置项.不幸的是,您没有共享足够的代码来理解这一点.无论哪种方式,根据文档声明您的信号.

Also, you do not seem to declare the signal in your QML Text item. I am not sure if it is a custom C++ item or a built-in one. You have not shared enough code unfortunately to understand that bit. Either way, declare your signal as per documentation.

因此,请尝试以下代码:

Therefore, try this code out:

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

完成后,您就快准备好了.您需要确保将HolidayTask确保已注册到QML,并且还需要按以下方式更改main.cpp中的连接语法:

Once that is done, you are almost ready. You need to have your HolidayTask registered to QML for sure, and you also need to change the connect syntax in your main.cpp as follows:

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

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

In short, you need to trigger your QML signal handler this way, and not via SLOT.

此外,请注意您的connect语法已损坏,因为它缺少结尾的右括号.这需要解决.

Also, note that your connect syntax is broken as it is missing the closing brackets at the end. That needs to be fixed.

我什至会考虑删除指针分配,并为此使用基于值或基于引用的传递.

I would even consider removing the pointer assignment and use value or reference based passing for this.

这篇关于从C ++(Qt5)向QML项目发送信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆