我想从C ++向我的QML文件中的Slot发送一个Signal。
我已经让它在没有原始类型参数的情况下工作,但是如果我想将QString
发送到我的QML Slot,我在连接时会出错。
我在main.cpp中连接
QObject *contentView = rootObject->findChild<QObject*>(QString("contentView"));
QObject::connect(&myObj, SIGNAL(finishedGatheringDataForItem(QString)),
contentView, SLOT(updateViewWithItem(QString)));
我的qml文件的相关部分
Rectangle {
objectName: "contentView"
function updateViewWithItem(string) { console.log('got some Items'); } // slot
}
错误:
Object::connect: No such slot QDeclarativeRectangle_QML_2::updateViewWithItem(QString)
答案 0 :(得分:34)
我认为最好检查本教程:
http://doc.qt.io/qt-4.8/qtbinding.html
特别是本节:
http://doc.qt.io/qt-4.8/qtbinding.html#receiving-signals
我认为你在这种情况下的错误可能是你没有将它声明为一个插槽,或者你没有让它成为可调用的。这两个选项都在Qt Tutorial中进行了解释。
此外,您需要使用QVariant才能在C ++和QML之间交换数据。 您还可以注册类型,例如小部件和东西,以便您可以在QML中将它们用作像“矩形”这样的“本机”类型。在大多数情况下,建议不要这样做,除非您需要某些外部类或某些数据,否则您无法在QML界面中显示。
QVariant的原因是基于脚本的QML方法。 QVariant基本上包含您的数据和数据类型的描述,以便QML知道如何正确处理它。这就是为什么你必须使用String,int等在QML中指定参数。但是与C ++的原始数据交换仍然是QVariant
之前我使用过qmlRegisterType,但对于简单数据类型来说这是一个非常不方便的解决方案。它更适用于更复杂的数据,例如QML本身不支持或扩展{J}的自定义窗口小部件,画布或视频元素。这是在QML和C ++之间交换数据的更方便的方法,并且在第一个实例中不需要信号或插槽,因为QStandardItemModel自动更新GUI。要使用QStandardItemModel,您需要使用qmlRegisterType注册Type ..然后可以在基于模型的视图中使用模型,例如ListView等。
我附上了这个主题的教程,它描述了如何使用QListModel。
答案 1 :(得分:33)
在这种情况下你应该使用连接(也许这是唯一的连接方式)。
将您的对象 myObj 放到setContextProperty
qmlVectorForm->rootContext()->setContextProperty("YourObject", myOb);
您的信号是
finishedGatheringDataForItem(QString signalString)
在QML文件中,添加下面的Connectios:
Connections {
target: YourObject
onFinishedGatheringDataForItem: {
qmlString = signalString
}
}
答案 2 :(得分:1)
没有Connections
和任何上下文的解决方案是通过不连接信号槽,而是连接信号信号。找到here。
示例代码如下。
qml:
Window{
signal qmlSend(string textOut)
signal qmlReceive(string textIn)
onQmlReceive:{
console.log(textIn)
}
}
Background类的头文件包含
public signals:
void cppSend(QString textOut);
public slots:
void cppReceive(QString textIn);
main.cpp以这种方式连接它们:
1。从qml到cpp:
QObject::connect(qmlRootObject, SIGNAL(qmlSend(QString)),
backgroundObject, SLOT(cppReceive(QString)));
2。从cpp到qml:
QObject::connect(backgroundObject, SIGNAL(cppSend(QString)),
qmlRootObject, SIGNAL(qmlReceive(QString)));
答案 3 :(得分:1)
我尝试了很多解决方案来成功仅从 C++ 信号更新 QML,但许多解决方案都不起作用。 此解决方案有效并经过测试,它基于以下答案:https://stackoverflow.com/a/59502860/2486332(@Adriano Campos)
您可以使用信号将数据从 C++ 发送到 qml,如下所示:
main.cpp:
#include <QQmlContext>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
// Class init
YourClass yourObject;
// Embedding C++ Objects into QML with Context Properties
QQmlContext* ctx = engine.rootContext();
ctx->setContextProperty("yourObject", &yourObject);
return app.exec();
}
main.qml:
import QtQuick 2.6
Window {
id: mainWindow
Connections {
target: yourObject
onSignalData: {
console.log("Data: " + signal_param)
textToChange.text = "Changed to: " + signal_param
}
}
Text {
id: textToChange
text: "beforeChange"
}
}
yourClass.h:
class YourClass : public QObject
{
Q_OBJECT
signals:
// Signal from YourClass
void signalData(QString signal_param);
}
你的类.cpp:
emit signalData("Hello QML"); // Signal from yourClass
有关“如何将带有信号和插槽的 Qt C++ 类暴露给 QML”的完整教程可在此页面上找到:https://felgo.com/cross-platform-development/how-to-expose-a-qt-cpp-class-with-signals-and-slots-to-qml
答案 4 :(得分:-1)
为什么不使用 rootContext?
在 C++ 方面你有:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
//--------------------------------------------------------
#include <myClass.h>
//--------------------------------------------------------
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//--------------------------------------------------------
myClass * myobj = new myClass(&app);
//--------------------------------------------------------
//--------------------------------------------------------
engine.rootContext()->setContextProperty("myobj",myobj);
//--------------------------------------------------------
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
在 qml 方面你有:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
//--------------------------------------------------------
Component.onCompleted: {
myobj.onSomeSignal.connect(signalHandling)
}
//--------------------------------------------------------
//--------------------------------------------------------
function signalHandling(){
console.log("Signal emitted from c++ side")
}
//--------------------------------------------------------
}