Qt Quick - 如何仅通过 C++ 代码与 qml 属性 交互
Qt Quick - How to interact with a qml property exclusively from the c++ code
在使用 Visual Studio 2019 编写的 Qt5 项目中,我必须与来自 c++ class 的几个 qml 属性进行非常密切的通信。更确切地说,我需要能够从我的 c++ class 更改 qml window 的 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++ class 中编写所有代码,而没有 ANY 行代码qml 方面?
尝试将 Q_SIGNAL 和 Q_INVOKABLE 替换为 Q_PROPERTIES 并实施所有 slots/signals。在 UI 中,在 mainWindow 中使用 属性 绑定,如对所有 4 个属性的 "x: mfMainFormHelper.x"。
不要使用赋值运算符,它会破坏 属性 绑定(即通知停止在 属性 上工作)
我终于可以通过以下方式解决我的问题了:
- 我创建了一个 class 继承自
QObject
- 在加载 qml
后,我从 QQmlApplicationEngine
获得了我的 qml window 指针作为 QWindow
对象
- 我使用 connect() 函数连接我需要的信号,如下例所示:
connect(pQtWindow, &QWindow::widthChanged, this, &WQtFormHelper::onFormWidthChanged);
我使用 Qt 代理读取和写入我的 window 属性,如下例所示:
int value = QQmlProperty(pQtWindow, "width").read().value<int>();
QQmlProperty(pQtWindow, "width").write(1000);
(注意 pQtWindow->setProperty("width", 1000);
也有效)
在使用 Visual Studio 2019 编写的 Qt5 项目中,我必须与来自 c++ class 的几个 qml 属性进行非常密切的通信。更确切地说,我需要能够从我的 c++ class 更改 qml window 的 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++ class 中编写所有代码,而没有 ANY 行代码qml 方面?
尝试将 Q_SIGNAL 和 Q_INVOKABLE 替换为 Q_PROPERTIES 并实施所有 slots/signals。在 UI 中,在 mainWindow 中使用 属性 绑定,如对所有 4 个属性的 "x: mfMainFormHelper.x"。
不要使用赋值运算符,它会破坏 属性 绑定(即通知停止在 属性 上工作)
我终于可以通过以下方式解决我的问题了:
- 我创建了一个 class 继承自
QObject
- 在加载 qml 后,我从
- 我使用 connect() 函数连接我需要的信号,如下例所示:
connect(pQtWindow, &QWindow::widthChanged, this, &WQtFormHelper::onFormWidthChanged);
我使用 Qt 代理读取和写入我的 window 属性,如下例所示:
int value = QQmlProperty(pQtWindow, "width").read().value<int>();
QQmlProperty(pQtWindow, "width").write(1000);
(注意
pQtWindow->setProperty("width", 1000);
也有效)
QQmlApplicationEngine
获得了我的 qml window 指针作为 QWindow
对象