C++Qt中QML插槽的信号
C++ signal to QML slot in Qt
我想将信号从C++发送到QML文件中的插槽。我已经让它在没有基元类型参数的情况下工作,尽管如果我想向我的 QML 插槽发送QString
,我在连接时会出现错误。
我在主连接.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)
在这种情况下,您应该使用连接(也许这是唯一的连接方式(。
-
将您的对象 myObj 放到 QML 文件中
setContextProperty
qmlVectorForm->rootContext()->setContextProperty("YourObject", myOb);
-
您的信号是
finishedGatheringDataForItem(QString signalString)
-
在QML文件中,添加以下Connectios喜欢:
Connections { target: YourObject onFinishedGatheringDataForItem: { qmlString = signalString } }
我认为最好检查本教程:
http://doc.qt.io/qt-4.8/qtbinding.html
尤其是这一节:
http://doc.qt.io/qt-4.8/qtbinding.html#receiving-signals
我认为您在这种情况下的错误可能是您没有将其声明为插槽,或者您没有使其可调用。Qt教程中对这两个选项都有解释。
此外,您需要使用 QVariant 才能在 C++ 和 QML 之间交换数据。您还可以注册类型,例如小部件和其他东西,以便您可以在QML中将它们用作矩形等"本机"类型。在大多数情况下,不建议这样做,除非您需要某些特定的外部类或某些无法在 QML 界面中显示的数据。
QVariant 的原因是 QML 基于脚本的方法。QVariant 基本上包含您的数据和数据类型的描述,以便 QML 知道如何正确处理它。这就是为什么你必须在 QML 中使用 String、int 等指定参数的原因。但与C++的原始数据交换仍然是一个QVariant
我以前使用过qmlRegisterType,但是对于简单的数据类型来说,这是一个非常不方便的解决方案。它用于更复杂的数据,例如QML本身不支持的自定义小部件,画布或视频元素或扩展QStandardItemModels
。这是在QML和C++之间交换数据的更方便的方式,并且首先不需要信号或插槽,因为QStandardItemModel会自动更新GUI。要使用QStandardItemModel,您需要向qmlRegisterType注册类型。.然后,可以在基于模型的视图中使用该模型,例如列表视图等。
我附上了本主题的教程,它描述了如何使用 QListModel。
http://doc.qt.io/qt-4.8/qdeclarativemodels.html
对于那些也偶然发现这个问题的人,我想说一切都简单得多。你只需要来自C++的信号来QVariant
参数。例如:
QObject::connect(&recipient, SIGNAL(resTalk(QVariant)), engine.rootObjects().at(0)->findChild<QObject*>("winSettings"),
SLOT(showWithErrorNetwork(QVariant)));
我的信号声明如下:
signals:
void resTalk(QVariant res);
所以我在呼叫信号:
emit resTalk(true); //For more complex types, use 'emit yourSignal(QVariant(yourArg))'
这是我在 QML 中的插槽:
function showWithErrorNetwork(isNoError=false) {
if(!isNoError) {
visible = true
warningText.text = "Network error. Check the data."
warningText.visible = true
}
}
没有Connections
和任何上下文的解决方案不是连接信号插槽,而是连接信号信号。在这里找到。示例代码如下。
QML:
Window{
signal qmlSend(string textOut)
signal qmlReceive(string textIn)
onQmlReceive:{
console.log(textIn)
}
}
后台类的头文件包含
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)));
我已经尝试了很多解决方案来成功地从C++信号更新 QML,但许多解决方案都没有奏效。该解决方案有效并已经过测试,它基于以下答案:https://stackoverflow.com/a/59502860/2486332(@Adriano Campos(
您可以使用信号将数据从C++发送到 qml,如下所示:
主.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
有关"如何使用信号和插槽向QML公开Qt C++类"的完整教程,请参阅此页面:https://felgo.com/cross-platform-development/how-to-expose-a-qt-cpp-class-with-signals-and-slots-to-qml
为什么不使用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")
}
//--------------------------------------------------------
}
- 控制带有信号/插槽的Qt QML滑动视图
- Qt 信号/插槽问题
- Qt moveToThread,带有参数的信号/插槽
- moc 文件中缺少信号插槽
- 文档在哪里说明如果参数不是从末端删除参数,则无法从QT信号插槽连接中删除参数?
- 信号/插槽多线程 Qt
- 通过排队的QT信号插槽连接发送QSHAREDPOINTERS的QVECTOR
- Qimage没有通过信号插槽QT
- 使用 Qt5 的新信号/插槽实现向滑块发出信号
- 一个类中的QT信号/插槽,但从不同的线程发出
- 信号/插槽基类多继承
- 在QT C 中使用QMOVIE和信号/插槽之间在GIF中导航
- 在 for 循环中使用 lambda 函数连接信号插槽
- 不同类别的 2 个对象之间的信号/插槽
- 如何正确使用qt的信号/插槽系统
- Qt信号插槽视觉工作室:似乎未连接
- QACTION信号插槽中的无形UI
- Qt-连接触发动作中的信号/插槽
- Qt 信号插槽类范围类型
- 信号/插槽 Qt5 C++