c++ - 正确的 QML <-> C++ 声明式方法
问题描述
我在 C++ 层更新了一些数据结构。我必须在 qml 中显示它并将更改从 qml 层保存到 c++ 结构。我希望有一种声明性的方法来做到这一点,但我迫切地想要找到它。这是代码的一部分:
C++ 头文件:
#ifndef NODEINFO_H
#define NODEINFO_H
#include <QObject>
#include <QString>
class NodeInfo : public QObject {
Q_OBJECT
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
public:
NodeInfo(QObject *parent = 0);
virtual ~NodeInfo() {}
const QString& label() const;
void setLabel(const QString& val);
signals:
void labelChanged();
private:
QString d_label;
};
#endif // NODEINFO_H
C++ 正文:
#include "nodeinfo.h"
#include <QDebug>
NodeInfo::NodeInfo(QObject *parent) : QObject(parent), d_label("Test string") {
}
const QString &NodeInfo::label() const {
qDebug() << "NodeInfo::label: getter";
return d_label;
}
void NodeInfo::setLabel(const QString &val) {
qDebug() << "NodeInfo::label: setter - " << val;
d_label = val;
emit labelChanged();
}
主文件
#include <QGuiApplication>
#include <QDebug>
#include <QQmlContext>
#include <QQuickView>
#include <QQmlApplicationEngine>
#include "nodeinfo.h"
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
// qmlRegisterType<NodeInfo>("NodeInfo", 1, 0, "NodeInfo");
NodeInfo nodeDescr;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("nodeData", &nodeDescr);
const QUrl url(QStringLiteral("qrc:/main.qml"));
engine.load(url);
QObject *root = engine.rootObjects().value(0);
if (QWindow *window = qobject_cast<QWindow *>(root))
window->show();
else
return -1;
return app.exec();
}
qml代码:
import QtQuick 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow {
id: root
width: 360
height: 520
visible: true
// property alias a_label: nodeData.label
Column {
anchors.fill: parent
TextInput {
id: simpleTxt
text: nodeData.label
}
Text {
id: txt
text: nodeData.label
}
Button {
text: "writeProp"
onClicked: nodeData.label = simpleTxt.text
}
// Binding {
// target: nodeData
// property: "label"
// value: simpleTxt.text
// }
}
}
因此,当我在 TextInput 中编辑文本时,它应该自动在 c++ 代码中设置属性,但事实并非如此。只有当我按下按钮。正如您在评论中看到的那样,有一种绑定方式,它可以工作,但我希望这不是一种真正的方式。让我们想象一下,如果我的 c++ 结构中有 15-30 个或更多数据字段,并且如果我必须以这种方式进行 30 次绑定,或者我需要在每个数据字段上编写信号/插槽并连接它们,那么这完全是垃圾。但什么是正确的方法?任何想法表示赞赏
解决方案
text: nodeData.label
设置绑定 nodeData.label --> 文本(一个方向)。即,只要 nodeData.label 更改,文本就会更新。当用户在字段中键入一些文本时,此绑定将被销毁。
因此,如果您想在用户更改文本时更新 nodeData.label,则需要使用 onTextChaged 事件。
Text {
onTextChanged: nodeData.label = text
}
changed
还有一点需要注意:在发出适当的信号之前,您需要检查属性是否真的发生了变化。所以代码应该是这样的:
void NodeInfo::setLabel(const QString &val) {
qDebug() << "NodeInfo::label: setter - " << val;
if (d_label != val)
{
d_label = val;
emit labelChanged();
}
}
这将防止您的代码无休止的绑定循环。
推荐阅读
- .htaccess - 我如何从我的网站链接中删除“索引”
- python - 遍历多个列表以找到最佳的整体组合
- swift - UITableView 在调用 reloadData 方法时返回 nil
- c++builder - TTrackBar > 未能绘制背景 > 如何修复?
- amazon-s3 - 尝试使用 Pyspark 访问 AWS S3 时出错
- python - python 程序中的多个 lambdas 导致 VS Code 报告“问题”
- php - 通过 SELECT Query 在 WHERE 中进行多个 AND SQL 服务器 2012
- scrapy - `reddit` 是否会阻止爬虫移动到下一页?
- python - 如何在 python 中为用户输入的光标位置设置默认值?
- anylogic - 代理停止的来源