Qt Quick - 如何仅通过 c++ 代码与 qml 属性交互
Posted
技术标签:
【中文标题】Qt Quick - 如何仅通过 c++ 代码与 qml 属性交互【英文标题】:Qt Quick - How to interact with a qml property exclusively from the c++ code 【发布时间】:2020-02-20 22:20:14 【问题描述】:在使用 Visual Studio 2019 编写的 Qt5 项目中,我必须与来自 c++ 类的几个 qml 属性进行非常密切的沟通。更确切地说,我需要能够从我的 c++ 类中更改 qml 窗口的 x、y、宽度和高度属性,并且当这些属性发生更改时,我还需要接收通知,当然还需要知道新值。
通过在qml端编写部分代码,我可以找到以下解决方案:
qml 文件:
...
ApplicationWindow
id: mainWindow
...
onXChanged: if (mfMainFormHelper) mfMainFormHelper.onFormXChanged(mainWindow.x);
onYChanged: if (mfMainFormHelper) mfMainFormHelper.onFormYChanged(mainWindow.y);
onWidthChanged: if (mfMainFormHelper) mfMainFormHelper.onFormWidthChanged(mainWindow.width);
onHeightChanged: if (mfMainFormHelper) mfMainFormHelper.onFormHeightChanged(mainWindow.height);
Connections
target: mfMainFormHelper
onDoChangeX:
mainWindow.x = value;
onDoChangeY:
mainWindow.y = value;
onDoChangeWidth:
mainWindow.width = value;
onDoChangeHeight:
mainWindow.height = value;
...
WQtMainFormHelper.h
class WQtMainFormHelper : public QObject
Q_OBJECT
Q_SIGNALS:
void doChangeX(int value);
void doChangeY(int value);
void doChangeWidth(int value);
void doChangeHeight(int value);
...
public:
...
virtual Q_INVOKABLE void onFormXChanged(int value);
virtual Q_INVOKABLE void onFormYChanged(int value);
virtual Q_INVOKABLE void onFormWidthChanged(int value);
virtual Q_INVOKABLE void onFormHeightChanged(int value);
...
main.cpp
...
WQtMainFormHelper mainFormHelper;
m_pQTEngine->rootContext()->setContextProperty("mfMainFormHelper", &mainFormHelper);
...
这个解决方案效果很好,但是被我的老板拒绝了,因为他要求所有这部分代码都只能在 c++ 端编写。
所以我的问题是:如何实现与上述完全相同的功能,但在我的 c++ 类中编写所有代码,而在 qml 端没有 ANY 行代码?
【问题讨论】:
【参考方案1】:尝试将 Q_SIGNAL 和 Q_INVOKABLE 替换为 Q_PROPERTIES 并实现所有插槽/信号。并在 UI 中使用 mainWindow 中的属性绑定,例如所有 4 个属性的“x: mfMainFormHelper.x”。
不要使用赋值运算符,它会破坏属性绑定(即通知停止对该属性的工作)
【讨论】:
【参考方案2】:我终于可以通过以下方式解决我的问题了:
-
我创建了一个继承自
QObject
的类
在加载 qml 后,我从 QQmlApplicationEngine
获得了我的 qml 窗口指针作为 QWindow
对象
我使用 connect() 函数来连接我需要的信号,如下例所示:
connect(pQtWindow, &QWindow::widthChanged, this, &WQtFormHelper::onFormWidthChanged);
我使用 Qt 代理来读取和写入我的窗口属性,如下例所示:
int value = QQmlProperty(pQtWindow, "width").read().value<int>();
QQmlProperty(pQtWindow, "width").write(1000);
(注意 pQtWindow->setProperty("width", 1000);
也有效)
【讨论】:
以上是关于Qt Quick - 如何仅通过 c++ 代码与 qml 属性交互的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Qt Quick 中将 QML 项目转换为相应的 C++ 项目