如何调用组件内定义的函数?

时间:2017-11-27 09:20:50

标签: c++ qt qml qt5 qtquick2

设置

我的系统是KUbuntu 17.10,Qt 5.9。

我有一个stackview,它实际上拥有更多组件,但为了简洁起见,我将它们删除了。基本上,当按下“Return the Item”按钮时,C ++端会捕获submitReturnButton信号。捕获方没有任何状态,它只是尝试发送文本设置在标签上。

代码

的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QQuickWindow>

#include "returnserver.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    //boilerplate ends here

    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    QObject* returnStatusLabel = engine.findChild<QObject*>("returnStatusLabel");

    ReturnServer returner(returnStatusLabel);

    QObject::connect(window, SIGNAL(submitReturnForm(QString)), &returner, SLOT(returnPressed(QString)));
    return app.exec();
}

returnserver.h

#ifndef RETURNSERVER_H
#define RETURNSERVER_H

#include <QObject>
#include <QVariant>
#include <QString>
#include <QQuickWindow>

class ReturnServer : public QObject
{
    Q_OBJECT

    QObject* target;
public:
    ReturnServer(QObject* target, QObject* parent = nullptr);

public slots:
    void returnPressed(const QString& str);
};

#endif // RETURNSERVER_H

returnserver.cpp

#include "returnserver.h"
#include <QString>
#include <QVariant>

ReturnServer::ReturnServer(QObject* target, QObject *parent) :
    target(target),
    QObject(parent)
{

}

void ReturnServer::returnPressed(const QString& str)
{
    //qDebug() << "the signal got to slot correctly";
    QVariant status = "Returned";

//    emit statusReady(QVariant::fromValue(status));
    QMetaObject::invokeMethod(target, "setReturnStatus", Q_ARG(QVariant, status));
}

QML

main.qml 并不真正相关,只是为了表明该应用具有stackview并分解为组件

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Borrowment terminal")

    signal submitReturnForm(string itemID)

    property int lineEditLength: 120
    background: Rectangle
    {
        id: mainBackground
        color: "gray"
    }

    StackView
    {
        id: stack
        initialItem: returnPageComponent
    }

    Component
    {
        id: returnPageComponent
        ReturnPage{}
    }
}

ReturnPage.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2

Item {
    id: returnPageView

    ColumnLayout {
        id: returnPageMenu
        x: 213
        y: 99
        width: 200
        height: 282
        Layout.margins: 20

        //redundant, just to make it compile
        Rectangle {
            width: lineEditLength
            height: 40
            color: "white"
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
            TextInput {
                id: itemIDEdit
                width: parent.width
                height: parent.height
                font.pixelSize: 20
                maximumLength: 8
            }


        }

        //this label I want to set
        Label
        {
            id: returnStatusLabel
            objectName: "returnStatusLabel"
            function setReturnStatus(status) {
                console.log("set return status to " + status)
                ReturnPage.returnStatus = status
            }
            text: "empty"
            width: 100
            height: 20
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
            font.pointSize: 14

        }

        Button {
            id: returnItemButton
            width: 75
            height: 30
            text: "Return the Item"
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
            onClicked:  submitReturnForm(itemIDEdit.text)
        }    
    }
}

截图

enter image description here

问题

我如何调用/设置returnStatusLabel到C ++端发送的某些文本,因为它位于不同的组件中?

我尝试了什么

  1. main.qml中创建函数,并以root对象作为目标从C ++调用它。

    这确实调用了该函数,但未设置文本。我怀疑这是关于不使用正确的对象的事情,所以关于生命的问题。

  2. 在标签本身中创建函数,在C ++中查找对象并以对象作为参数调用该函数

    在这种情况下,函数根本没有被调用,尽管调试器没有抱怨没有正确设置连接。

1 个答案:

答案 0 :(得分:2)

代码太多了......而且很少有文字解释你的想法,因此回答是非常复杂的,我可能会完全忽略这一点。

  

如何将returnStatusLabel调用/设置为从C ++端发送的某些文本,因为它位于不同的组件中?

你不能。 Component只是一个声明,或者更好:一个配置的工厂来生成某种实例。但是,没有可以调用函数的此类对象的实例。

但我在其他组件中看不到任何。我只能看到你在C ++方面犯了QML方面的错误。

引用文档:

  

Warning:虽然可以使用C ++访问和操作深入到对象树中的QML对象,但我们建议您不要在应用程序测试和原型设计之外采用这种方法。 QML和C ++集成的一个优势是能够独立于C ++逻辑和数据集后端实现QML用户界面,如果C ++方面深入到QML组件中直接操作它们,这种策略就会中断。例如,如果新组件缺少必需的objectName,则很难将QML视图组件交换到另一个视图。对于C ++实现,最好尽可能少地了解QML用户界面实现和QML对象树的组成。

正确的方法是在QML中创建ResponseServer的实例,这样您就可以轻松地在此处执行 wireing ,或者展示C ++的{{1}实例作为上下文属性或QML的单例实例 基线是:用QML进行信号接线。提供您可以轻松绑定的属性值。