Qt 连接事件到非 QObject 类型

Posted

技术标签:

【中文标题】Qt 连接事件到非 QObject 类型【英文标题】:Qt Connect Event to non-QObject Types 【发布时间】:2019-09-15 04:55:58 【问题描述】:

我有一个数据模型对象,它带有一个用于处理 Qt 事件的方法。但是,当我尝试将事件处理程序连接到此方法时,会出现编译时错误。问题是connect 模板最终会在第四个参数上执行static_cast<void (QObject::*)(double)>。由于我的数据模型不是从 QObject 继承的,因此此代码会生成错误 C2664:

指向的类型是不相关的;转换需要 reinterpret_cast、C-style cast 或 function-style cast

有没有办法将事件处理程序连接到非 QObject 类型?一个最小的例子:

struct DataModel 
    void handle(double)  
;

DataModel data;
QDoubleSpinBox spinBox;
connect(&spinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
    &data, &DataModel::handle);

鉴于所有“连接”方法所做的只是设置事件转发,因此这种类型要求似乎没有必要。我们不能在那里使用任何有效的函数指针是有原因的吗?

【问题讨论】:

【参考方案1】:

自 Qt 5 以来可用的新连接选项之一是使用 lambda 作为 slots,在这些情况下非常有用:

// adapt the capture to your specific situation
connect(&spinBox, qOverload<double>(&QDoubleSpinBox::valueChanged),
       [&data](double arg)  data.handle(arg); );

PS:我使用了一个较短的形式来选择正确的重载,您可能会发现它很有用:qOverload&lt;double&gt;(...)

【讨论】:

这在功能上与我想出的答案相同,但由于使用 lambda 而不是 std::bind 更简洁。我无法让较短的 qOverload 表单在 Windows 上工作。【参考方案2】:

还有一个连接模板重载可以接受任何类型的函数对象。因此,我能够将我的connect 方法调用重写为:

connect(&spinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
    std::bind(std::mem_fn(&DataModel::handle), &data, std::placeholders::_1);

然后 Qt 不会尝试将任何内容转换为不兼容的类型。

【讨论】:

以上是关于Qt 连接事件到非 QObject 类型的主要内容,如果未能解决你的问题,请参考以下文章

Qt智能指针

2020-11-20 Qt事件循环

QT QObject分析

connect(QObject*, SIGNAL(signal()), functor) 未在 qt5 中连接

Qt入门教程QObject篇线程和QOBject

Qt入门教程QObject篇线程和QOBject