【问题标题】:How to store an instance of QPropertyChangeHandler?如何存储 QPropertyChangeHandler 的实例?
【发布时间】:2023-02-25 07:38:13
【问题描述】:

QProperty::onValueChange() 返回一个 QPropertyChangeHandler 对象,我认为应该将其存储为成员变量,这样它就不会被销毁并因此注销 Functor。

由于 QPropertyChangeHandler 是一个采用 Functor 的模板类,我需要提供我将要使用的 Functor 的类型,但我不确定在那里放置什么类型。

我应该如何存储返回的QPropertyChangeHandler对象?


以下是我迄今为止最好的尝试:

测试.h

#ifndef PROP_TEST
#define PROP_TEST

#include <QObject>
#include <QProperty>
#include <QString>
#include <QPropertyChangeHandler>
#include <functional>

class PropTest : public QObject {
    Q_OBJECT

public:
    QProperty<QString> m_property;

    PropTest();
    ~PropTest() = default;

    // QString m_property;

    QPropertyChangeHandler< std::function<void()> > propertyChangeHandler;

    void TestFunction();
};

#endif

Proptest.cpp

#include <QObject>
#include <QString>
#include <QDebug>
#include <QApplication>

#include "prop_test.h"

PropTest::PropTest() { // <- error occurs here
    this->propertyChangeHandler = this->m_property.onValueChanged(&PropTest::TestFunction);
}

void PropTest::TestFunction() {
    // further processing
}

int main(int arc, char* argv[]) {

    auto app = QApplication(arc, argv);

    auto ob = new PropTest{};

    ob->m_property = "String";
    ob->m_property = "New";

    app.exec();
}

但我得到的只是这个不熟悉的错误:

[build] prop_test.cpp: In constructor 'PropTest::PropTest()':
[build] prop_test.cpp:11:20: error: no matching function for call to 'QPropertyChangeHandler<std::function<void()> >::QPropertyChangeHandler()'
[build]    11 | PropTest::PropTest() {
[build]       |                    ^

我发现错误发生的地方很奇怪。

【问题讨论】:

  • 乍一看,您似乎已将成员变量声明为采用带有 1 bool 参数的函数。您的 TestFunction 方法采用参数,因此它将进入 std::function&lt;void()&gt; 。这是你要问的吗?
  • 很抱歉造成混淆,这一定是准备 MRE 时的错字。

标签: c++ qt qt6


【解决方案1】:

让我们按顺序进行。
免责声明:不幸的是,我错误地下载了非英语版本的 Visual Studio 并且从未将其更改回来,因此我没有确切的错误消息。


您应该注意到的第一个错误是QPropertyChangeHandler&lt;[...]&gt; 没有默认构造函数。

这很容易通过移动来纠正

this->propertyChangeHandler = this->m_property.onValueChanged(&PropTest::TestFunction);

从构造函数的主体中进入类的初始化列表。


解决了这个错误,是时候解决类型混乱了。

PropTest::TestFunction方法的确切类型是void(PropTest::*)();这是与 void() 不同的类型,因为本质上,对于类的方法,指针 this 始终是一个参数。

因为 this 被认为是一个参数,所以你不能这样做:

propertyChangeHandler(m_property.onValueChanged(&PropTest::TestFunction))

如果您尝试,您会收到来自 Qt 的错误消息(来自 QProperty.h 中的静态断言):Functor callback must be callable without any parameters

假设您要在处理程序中连接的函数需要是对象方法(不是单独的函数,不是静态方法),有几种方法可以解决这个问题:

  1. 第一个解决方案使用仿函数,将您的对象作为其成员。
    标头:

    class PropTest;
    
    struct TestFunctor {
    public:
        TestFunctor(PropTest* propTestObject);
        void operator () () const;
    
    private:
        PropTest* object;
    
    };
    

    和来源:

    TestFunctor::TestFunctor(PropTest* propTestObject)
        : object(propTestObject)
    {
    }
    void TestFunctor::operator()() const {
        object->TestFunction();
    }
    

    使用该解决方案(仅该解决方案),必须将 propertyChangeHandler 的类型更改为 QPropertyChangeHandler&lt;TestFunctor&gt; 并使用
    propertyChangeHandler( m_property.onValueChanged(TestFunctor(this)))

  2. 第二种解决方案是使用 lambda。例如:

    PropTest::PropTest()
        : QObject(),
        propertyChangeHandler(m_property.onValueChanged(std::function<void()>([=]() { this->TestFunction(); })))
    {
    }
    

    propertyChangeHandler 的类型是 QPropertyChangeHandler&lt; std::function&lt;void()&gt; &gt; 如果您决定以这种方式进行(即与您的问题相同)。

  3. 第三种解决方案是bindTestFunction方法。

    PropTest::PropTest()
        : QObject(),
        propertyChangeHandler(m_property.onValueChanged(std::function<void()>(std::bind(&PropTest::TestFunction, this))))
    {
    }
    
  4. 如果您可以将类方法 TestFunction() 变成一个单独的函数或一个静态方法,它会大大简化问题。 propertyChangeHandler 的类型需要分别为QPropertyChangeHandler&lt;void()&gt;(对于单独的函数)或QPropertyChangeHandler&lt;void(*)()&gt;(对于静态方法)。

    最后,它编译了!!

    PS:如果函数不需要附加到对象实例,我会使用解决方案 4。否则,我会选择解决方案 2 或解决方案 3。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2020-08-22
    • 2010-12-27
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    相关资源
    最近更新 更多