无法找出将信号从 qml 绑定到 cpp 插槽的正确方法
Can't figure out the right way to bind signals from qml to cpp slots
我正在使用 QT 5.7。
我的 main.qml
文件的根元素是 'ApplicationWindow'(顺便说一句,尽管它们有效,但它总是强调可见、宽度和高度为无效属性。我想知道它的修复方法或正确的方法因为我不能在设计器中编辑它)。
这是它的代码:
ApplicationWindow {
visible: true
width: 640
height: 480
Rectangle{
signal mSend()
anchors.fill: parent
Button{
id: bSend
onClicked: {
parent.mSend()
}
}
}
}
现在我正尝试以这种方式将 mSend
信号绑定到 CPP 插槽:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QObject>
#include <QQuickView>
#include <QQuickItem>
class Chat: public QObject{
Q_OBJECT
public Q_SLOTS:
void sendMessage(){
qDebug() << "CPP SLOT sendMessage called";
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QQuickView view(&engine, Q_NULLPTR);
QObject *item = view.rootObject();
Chat chat;
if(item){
qDebug() << "Item found";
QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
}else{
qDebug() << "item is null";
}
return app.exec();
}
#include "main.moc"
但结果是Item is null
。我一直在关注这个 guide,但我无法在 QML 中修改 QMLApplicationEngine 和 ApplicationWindow。
TIA
注意:我正在使用 Q_SLOTS
因为我也在使用 Boost 来合并 Socket IO 库。
您应该将信号从矩形移动到根对象:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
ApplicationWindow {
id: appWindow
visible: true
width: 640
height: 480
signal mSend()
Rectangle{
anchors.fill: parent
Button{
id: bSend
onClicked: {
appWindow.mSend()
}
}
}
}
根对象可直接通过 QQmlApplicationEngine 获得
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QObject *item = engine.rootObjects().first();
Chat chat;
if(item){
qDebug() << "Item found";
QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
}else{
qDebug() << "item is null";
}
return app.exec();
与其挖掘 QML 对象并从 C++ 中弄乱它们,我强烈建议将您的 Chat
对象公开给 QML。这就是 QML 和 C++ 集成设计的工作方式。您有多种选择。无论哪种方式,您都可以直接从 Button::onClicked
信号处理程序调用 Chat::sendMessage()
。
QML 类型
您可以使用 qmlRegisterType()
将 Chat
注册为 QML 类型,这样您就可以在 QML 中创建实例。
main.cpp:
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<Chat>("foo.bar", 1, 0, "Chat"); // <==
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
main.qml:
import QtQuick 2.0
import QtQuick.Controls 2.0
import foo.bar 1.0
ApplicationWindow {
Chat {
id: chat
}
Button {
onClicked: chat.sendMessage(...)
}
}
QML 单例类型
您可以使用 qmlRegisterSingletonType()
将 Chat
注册为 QML 单例类型,这样您就可以方便地在 QML 中的任何地方访问同一个实例。
main.cpp
static QObject *chatInstance(QQmlEngine *engine, QJSEngine *)
{
return new Chat(engine);
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterSingletonType<Chat>("foo.bar", 1, 0, "Chat", chatInstance); // <==
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import foo.bar 1.0
ApplicationWindow {
Button {
onClicked: Chat.sendMessage(...)
}
}
上下文 属性
如果您必须在 C++ 中创建 Chat
实例,您可以使用 QQmlContext::setContextProperty()
for the QML engine's root context 将其设置为上下文 属性。请注意,您必须在 属性 之前设置 加载引用上下文 属性.
的 QML
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Chat chat;
engine.rootContext()->setContextProperty("chat", &chat); // <==
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
Button {
onClicked: chat.sendMessage(...)
}
}
我正在使用 QT 5.7。
我的 main.qml
文件的根元素是 'ApplicationWindow'(顺便说一句,尽管它们有效,但它总是强调可见、宽度和高度为无效属性。我想知道它的修复方法或正确的方法因为我不能在设计器中编辑它)。
这是它的代码:
ApplicationWindow {
visible: true
width: 640
height: 480
Rectangle{
signal mSend()
anchors.fill: parent
Button{
id: bSend
onClicked: {
parent.mSend()
}
}
}
}
现在我正尝试以这种方式将 mSend
信号绑定到 CPP 插槽:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QObject>
#include <QQuickView>
#include <QQuickItem>
class Chat: public QObject{
Q_OBJECT
public Q_SLOTS:
void sendMessage(){
qDebug() << "CPP SLOT sendMessage called";
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QQuickView view(&engine, Q_NULLPTR);
QObject *item = view.rootObject();
Chat chat;
if(item){
qDebug() << "Item found";
QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
}else{
qDebug() << "item is null";
}
return app.exec();
}
#include "main.moc"
但结果是Item is null
。我一直在关注这个 guide,但我无法在 QML 中修改 QMLApplicationEngine 和 ApplicationWindow。
TIA
注意:我正在使用 Q_SLOTS
因为我也在使用 Boost 来合并 Socket IO 库。
您应该将信号从矩形移动到根对象:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
ApplicationWindow {
id: appWindow
visible: true
width: 640
height: 480
signal mSend()
Rectangle{
anchors.fill: parent
Button{
id: bSend
onClicked: {
appWindow.mSend()
}
}
}
}
根对象可直接通过 QQmlApplicationEngine 获得
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QObject *item = engine.rootObjects().first();
Chat chat;
if(item){
qDebug() << "Item found";
QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
}else{
qDebug() << "item is null";
}
return app.exec();
与其挖掘 QML 对象并从 C++ 中弄乱它们,我强烈建议将您的 Chat
对象公开给 QML。这就是 QML 和 C++ 集成设计的工作方式。您有多种选择。无论哪种方式,您都可以直接从 Button::onClicked
信号处理程序调用 Chat::sendMessage()
。
QML 类型
您可以使用 qmlRegisterType()
将 Chat
注册为 QML 类型,这样您就可以在 QML 中创建实例。
main.cpp:
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<Chat>("foo.bar", 1, 0, "Chat"); // <== QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
main.qml:
import QtQuick 2.0 import QtQuick.Controls 2.0 import foo.bar 1.0 ApplicationWindow { Chat { id: chat } Button { onClicked: chat.sendMessage(...) } }
QML 单例类型
您可以使用 qmlRegisterSingletonType()
将 Chat
注册为 QML 单例类型,这样您就可以方便地在 QML 中的任何地方访问同一个实例。
main.cpp
static QObject *chatInstance(QQmlEngine *engine, QJSEngine *) { return new Chat(engine); } int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterSingletonType<Chat>("foo.bar", 1, 0, "Chat", chatInstance); // <== QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.0 import QtQuick.Controls 2.0 import foo.bar 1.0 ApplicationWindow { Button { onClicked: Chat.sendMessage(...) } }
上下文 属性
如果您必须在 C++ 中创建 Chat
实例,您可以使用 QQmlContext::setContextProperty()
for the QML engine's root context 将其设置为上下文 属性。请注意,您必须在 属性 之前设置 加载引用上下文 属性.
main.cpp
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; Chat chat; engine.rootContext()->setContextProperty("chat", &chat); // <== engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.0 import QtQuick.Controls 2.0 ApplicationWindow { Button { onClicked: chat.sendMessage(...) } }