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"。

不要使用赋值运算符,它会破坏 属性 绑定(即通知停止在 属性 上工作)

我终于可以通过以下方式解决我的问题了:

  1. 我创建了一个 class 继承自 QObject
  2. 在加载 qml
  3. 后,我从 QQmlApplicationEngine 获得了我的 qml window 指针作为 QWindow 对象
  4. 我使用 connect() 函数连接我需要的信号,如下例所示: connect(pQtWindow, &QWindow::widthChanged, this, &WQtFormHelper::onFormWidthChanged);
  5. 我使用 Qt 代理读取和写入我的 window 属性,如下例所示: int value = QQmlProperty(pQtWindow, "width").read().value<int>();

    QQmlProperty(pQtWindow, "width").write(1000);

    (注意 pQtWindow->setProperty("width", 1000); 也有效)