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++ 项目

qml 和 c++ 与 qt quick 2 应用程序

Qt Widget Based Application与 Qt Quick Application的区别?

如何拦截 Qt Quick qml 事件?

Qt Quick 不翻译通过 Loader 加载的组件

如何通过按下和拖动在 Qt Quick/QML 画布中绘制一个矩形