如何调用组件内部定义的函数?
How to invoke a function defined inside of a component?
设置
我的系统是 KUbuntu 17.10,Qt 5.9。
我有一个 stackview,它实际上包含更多组件,但为了简洁起见,我将它们删掉了。基本上,当 "Return the Item" 按钮被按下时, submitReturnButton
信号在 C++ 端被捕获。捕捉端没有任何状态,它只是尝试发送文本以在标签上设置。
代码
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 不太相关,只是为了表明该应用程序具有堆栈视图并分解为组件
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)
}
}
}
截图
问题
我怎样才能 invoke/set 将 returnStatusLabel
发送到从 C++ 端发送的某些文本,因为它在不同的组件中?
我试过的
创建 main.qml
中的函数并从 C++ 调用它,并将根对象作为目标。
这确实调用了函数,但未设置文本。我怀疑这是关于没有使用正确的对象,所以关于生命周期。
在标签本身中创建函数,在 C++ 中找到对象并以对象作为参数调用函数
在这种情况下,函数根本没有被调用,尽管调试器没有抱怨连接设置不正确。
代码太多了...解释你的想法的文字很少,因此回答起来很复杂,我可能会完全错过重点。
How can I invoke/set the returnStatusLabel to some text sent from C++ end, given that it is in a different component?
你不能。组件只不过是一个声明,或者更好:一个配置好的工厂来生产某种类型的实例。但是,没有您可以调用函数的此类对象的实例。
但我在另一个组件 中没有看到任何蜂鸣声。我只能看到,您犯了从 C++ 端与 QML 端混合的错误。
引用文档:
Warning: While it is possible to use C++ to access and manipulate QML objects deep into the object tree, we recommend that you do not take this approach outside of application testing and prototyping. One strength of QML and C++ integration is the ability to implement the QML user interface separately from the C++ logic and dataset backend, and this strategy breaks if the C++ side reaches deep into the QML components to manipulate them directly. This would make it difficult to, for example, swap a QML view component for another view, if the new component was missing a required objectName. It is better for the C++ implementation to know as little as possible about the QML user interface implementation and the composition of the QML object tree.
正确的方法是在 QML 中创建 ResponseServer
的实例,以便您可以轻松地在此处执行 wireing,或者公开 C++ 生成的实例ResponseServer
作为上下文 属性 或 QML 的单例实例。
基线是:在 QML 中连接信号。以 properties 的形式提供您可以轻松绑定的值。
设置
我的系统是 KUbuntu 17.10,Qt 5.9。
我有一个 stackview,它实际上包含更多组件,但为了简洁起见,我将它们删掉了。基本上,当 "Return the Item" 按钮被按下时, submitReturnButton
信号在 C++ 端被捕获。捕捉端没有任何状态,它只是尝试发送文本以在标签上设置。
代码
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 不太相关,只是为了表明该应用程序具有堆栈视图并分解为组件
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)
}
}
}
截图
问题
我怎样才能 invoke/set 将 returnStatusLabel
发送到从 C++ 端发送的某些文本,因为它在不同的组件中?
我试过的
创建
main.qml
中的函数并从 C++ 调用它,并将根对象作为目标。这确实调用了函数,但未设置文本。我怀疑这是关于没有使用正确的对象,所以关于生命周期。
在标签本身中创建函数,在 C++ 中找到对象并以对象作为参数调用函数
在这种情况下,函数根本没有被调用,尽管调试器没有抱怨连接设置不正确。
代码太多了...解释你的想法的文字很少,因此回答起来很复杂,我可能会完全错过重点。
How can I invoke/set the returnStatusLabel to some text sent from C++ end, given that it is in a different component?
你不能。组件只不过是一个声明,或者更好:一个配置好的工厂来生产某种类型的实例。但是,没有您可以调用函数的此类对象的实例。
但我在另一个组件 中没有看到任何蜂鸣声。我只能看到,您犯了从 C++ 端与 QML 端混合的错误。
引用文档:
Warning: While it is possible to use C++ to access and manipulate QML objects deep into the object tree, we recommend that you do not take this approach outside of application testing and prototyping. One strength of QML and C++ integration is the ability to implement the QML user interface separately from the C++ logic and dataset backend, and this strategy breaks if the C++ side reaches deep into the QML components to manipulate them directly. This would make it difficult to, for example, swap a QML view component for another view, if the new component was missing a required objectName. It is better for the C++ implementation to know as little as possible about the QML user interface implementation and the composition of the QML object tree.
正确的方法是在 QML 中创建 ResponseServer
的实例,以便您可以轻松地在此处执行 wireing,或者公开 C++ 生成的实例ResponseServer
作为上下文 属性 或 QML 的单例实例。
基线是:在 QML 中连接信号。以 properties 的形式提供您可以轻松绑定的值。