如何在类型注册后在QML信号处理程序中捕获C ++信号?

时间:2015-12-02 11:14:15

标签: c++ qt signals qml slot

我正在开发一个基本的qml-cpp应用程序,以了解如何与另一个进行交互。我有一个MessageSetter C ++类和一个main.qml。由于我希望了解双向通信,因此我使用setContextProperty将MessageSetter属性公开给qml,并使用qml(可实例化注册)注册了MessageSetter类。暴露的属性工作正常。现在,当单击一个qml按钮时,信号(qmlBtnClicked)成功捕获在MessageSetter插槽中(onQmlButtonClicked)。此插槽进一步发出另一个MessageSetter信号(colorChanged)。这个新的(C ++)信号应该在qml注册的MessageSetter的信号处理程序(onColorChanged)中捕获,但它在任何情况下都不会到达此处。下面是main.cpp代码:

int main(int argc, char *argv[])
{
   QGuiApplication app(argc, argv);
   QQmlApplicationEngine engine;
   qmlRegisterType<MessageSetter>("com.SkillLotto.MessageSetter", 1, 0, "SetMessage");

   MessageSetter data;
   engine.rootContext()->setContextProperty("msgSetter", &data);
   QQmlComponent component(&engine, QUrl::fromLocalFile("main.qml"));

   QObject *object = component.create()->findChild<QObject*>("setTextBtn");
   QObject::connect(object, SIGNAL(qmlBtnClicked()), &data, SLOT(onQmlButtonClicked()));

   return app.exec();
}

这是MessageSetter插槽,它发出另一个信号:

void MessageSetter::onQmlButtonClicked()
{
   emit colorChanged("red");
}

这是qml代码,永远不会调用此信号处理程序:

SetMessage{
    onColorChanged: {
        rect.color = color    //rect is some rectangle in this file.
    }
}

正如我所说,qml信号在C ++插槽中成功捕获,但我无法在qml信号处理程序中捕获此C ++信号。请帮忙。

我认为这个问题主要集中在qmlRegisterType()上,不应该与this question重复?我还想知道qmlRegisterType()和setContextProperty()是否不能同时使用?

2 个答案:

答案 0 :(得分:2)

由于您使用的是MessageSetter的两个不同实例,其中一个data位于main.cpp,另一个是新实例SetMessage。仅使用一个连接两个信号/插槽。

您期望来自onColorChanged的{​​{1}}信号,但信号来自SetMessage(在main.cpp中)。

如果要创建上下文属性,为什么需要实例化?

在main.qml文件中添加

data

答案 1 :(得分:1)

我认为您的代码应该运行良好。

我没有完整的代码,因此我不知道您是否实施了正确的方法。

为了使用qmlRegisterType获取信号,您需要一些要求。检查是否已实施Q_PROPERTY宏调用。任何可写的属性都应该有一个关联的NOTIFY信号,只要属性值发生变化就会发出该信号。

如果是这样,当您更改color组件中的SetMessage属性时,应触发信号onColorChanged

这里有一个示例,其中发出两个信号:第一个是在更新size属性时,第二个是在使用mouseClick调用C ++ MouseArea方法时。

顺便说一句,您不需要setContextProperty将C ++类与QML集成。 qmlRegisterType应该足够了。反之亦然,视您的需要而定。您可以同时使用两者,但随后可以使用两个不同的对象。这实际上取决于你想要达到的目标。

<强>的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "customitem.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    qmlRegisterType<CustomItem>("CustomItem", 1,0, "CustomItem");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

<强> customitem.h

#ifndef CUSTOMITEM_H
#define CUSTOMITEM_H

#include <QObject>

class CustomItem: public QObject
{
    Q_OBJECT

    /*
     * Any property that is writable should have an associated NOTIFY signal.
     * Ref: http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html#exposing-properties
     */

    Q_PROPERTY(int size READ size WRITE setSize NOTIFY sizeChanged)

public:
    CustomItem(QObject *parent = 0);

    int size() const;
    void setSize(int);

    Q_INVOKABLE void mouseClick();

private:
    int m_size;

signals:
    void sizeChanged(int size);
    void clicked();

public slots:
};

#endif // CUSTOMITEM_H

<强> customitem.cpp

#include "customitem.h"
#include <QDebug>

CustomItem::CustomItem(QObject *parent)
: QObject(parent), m_size(0)
{
}

int CustomItem::size() const
{
    return m_size;
}

void CustomItem::setSize(int size)
{
    m_size = size;
    emit sizeChanged(m_size);
}

void CustomItem::mouseClick()
{
    qDebug() << "CustomItem::mouseClick()";

    emit clicked();
}

<强> main.qml

import QtQuick 2.5
import QtQuick.Window 2.2
import CustomItem 1.0

Window {
    visible: true

    TextInput  {
        id: mySize
        x: 0
        y: 0
        text: "100"
    }

    CustomItem {
        id: customItem
        size: mySize.text

        onSizeChanged: console.log("size changed:", size)
        onClicked: console.log("onClicked!")
    }

    Rectangle {
        id: rect
        x: 50
        y: 50
        width: customItem.size
        height: customItem.size
        color: "red"

        MouseArea {
            anchors.fill: parent
            onClicked: { customItem.mouseClick() }
        }
    }
}