【问题标题】:How to connect a QML signal with a C++ slot?如何将 QML 信号与 C++ 插槽连接?
【发布时间】:2017-05-03 10:59:01
【问题描述】:

我对 QML 中的 MessageDialog 信号有疑问。在我的MessageDialog 中,我有两个按钮用于YesNo。我想用信号连接每个按钮。 这是我的 qml 文件:

import QtQuick 2.2
import QtQuick.Dialogs 1.1

Item{
    MessageDialog {
        signal qmlYesSig(string msg)
        signal qmlNoSig (string msg)
        title: "Send data?"
        icon: StandardIcon.Question
        text: "Do you want to save your data on the online platform?"
        detailedText: "Click Yes "
        standardButtons: StandardButton.Yes | StandardButton.No
        Component.onCompleted: visible = true
        onYes: qmlYesSig("From yes")
        onNo: qmlNoSig("From no")
    }
}

这是我的位置:

class MyClass : public QObject
{
    Q_OBJECT
public slots:
    void cppSlot(const QString &msg) {
        qDebug() << "Called the C++ slot with message:" << msg;
    }
};

这是我在 main 中使用它的方式:

QQuickView view(QUrl::fromLocalFile("window.qml"));
QObject *item = view.rootObject();
AddData myClass;
QObject::connect(item, SIGNAL(qmlSignal(QString)),
                 &myClass, SLOT(cppSlot(QString)));

view.show();

它给了我错误:

C2665: 'QObject::connect': 3 个重载都不能转换所有参数类型

我尝试了很多次,但我无法使 QML 信号和 C++ 插槽工作。 我也尝试了这里的示例Qt doc 并给了我同样的错误。

谁能告诉我如何为MessageDialog 连接 QML 信号和 C++ 插槽?

【问题讨论】:

  • 你在哪里定义了信号qmlSignal?不在QObject *item = view.rootObject();
  • 这是我第一次使用来自 qml 的信号。我真的不明白我应该做些什么。当按下按钮时,它会发出一个应该在 C++ 中捕获的信号,写吗?
  • 仍然,您可以调试您的view.rootObject() 并查看不是您定义信号的 MessageDialog。所以要么在你的根 Item 中定义它,要么在 C++ 中获取 MessageDialog 子对象来连接信号。
  • 我刚查了Qt Doc,我猜你可以使用view.rootObject()-&gt;childItems().first()(应该是你的MessageDialog)
  • 应该qmlSignalqmlYesSig

标签: c++ qt


【解决方案1】:

您可以将 C++ QObject 暴露给 QML 引擎并从 QML 端连接到 C++ QObject 的插槽:

在 C++ 文件中:

view.rootContext()->setContextProperty("object", this); // replace this with appropriate object

在 Qml 中:

qmlYesSig.connect(object.cppSlot);

【讨论】:

  • 一个更完整的例子将不胜感激。例如,您将连接代码放在 QML 的哪个位置?如何设置连接类型为排队连接?
  • 不知道如何将你的答案变成一个可行的例子。你能发布一个完整的工作示例吗?
【解决方案2】:

您的 QML 文件是:

Item{
    MessageDialog {
        signal qmlYesSig(string msg)
        signal qmlNoSig (string msg)

        [...]
    }
}

你的 C++ 代码是:

QObject *item = view.rootObject();
AddData myClass;
QObject::connect(item, SIGNAL(qmlSignal(QString)),
                 &myClass, SLOT(cppSlot(QString)));

这意味着您正在 QML 文件的根项中寻找一个名为“qmlSignal”的信号。 这个根项目很简单

Item{}

如您所见,没有名为“qmlSignal”的信号。

您必须在根项中定义信号并从消息框中发出它。

Item{
    signal qmlSignal(string msg)

    MessageDialog {
        onYes: parent.qmlSignal("From yes")
        onNo: parent.qmlSignal("From no")
    }
}

【讨论】:

  • 谢谢迪尔。那工作,但是当我使用“QObject item = view.rootObject();”时我遇到了一些错误它说:“无法将 'QQuickItem' 转换为 'QObject*'”。你知道这是为什么吗?
  • @Adi QQuickItem 是一个 QObject 所以问题可能是你忘记了#include &lt;QQuickItem&gt;
  • 是的,那是 :) 谢谢
  • 您将 rootObject 连接到信号。当 Item 是 PushButton 并且您有 2 个或更多按钮时怎么办?或者您不仅有按钮,还有许多其他带有信号的项目。您想按按钮类型命名每个信号吗? Ok 按钮有 okSignal,Canel 按钮有 cancelSignal 等等……不!这不是正确的方法
  • parent.qmlSignal 中使用parent 似乎对我不起作用:我得到TypeError: Property 'qmlSignal' of object QQuickRootItem(0x83e620) is not a function。解决方法是将id 分配给顶级项目,并使用它而不是parent
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多