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

标签 c++ qt qml qt5 qtquick2

我有一个包含以下内容的 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);

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

如果我尝试将 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*)));

通过使用具有完整 namespace 的对象起作用。否则签名在 QML 中将不匹配。

最佳答案

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

您正试图根据 id 查找 child ,而它是基于 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/29429879/

相关文章:

JavaScript 控制台和 QML WebView

c++ - 使用 class::factory(); 实现 operator<<

c# - C++ 中的 nullptr 与 C# 中的 null 相同吗?

c++ - 使用常量参数连接插槽

c++ - 无法访问 ListView 中的 QAbstractListModel 数据

qt - 如何使图像填充qml控件按钮

c++ - JUCE 无法在音频插件上插入按钮

c++ - 数组基址指针及其地址相同。为什么?

linux - 如何将 Dcmtk 与 Qt for Linux 正确链接?

c++ - 如何将鼠标/光标添加到非触摸手机的 QML 应用程序?