我正在开发一个基本的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()是否不能同时使用?
答案 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() }
}
}
}