简体   繁体   English

如何在 QObject::connect 中使用 QMetaMethod

[英]How to use QMetaMethod with QObject::connect

I have two instances of QObject subclasses and two QMetaMethod instances of signal in one of objects and slot in another object.我有两个 QObject 子类的实例和两个 QMetaMethod 实例在一个对象和另一个对象中的插槽中的信号。 I want to connect this signal and slot with each other.我想将这个信号和插槽相互连接起来。

I've looked through the qobject.h file and find that SIGNAL() and SLOT() macro are just add "1" or "2" character to the beginning of method signature so it looks like it should be possible to add the same character to the beginning of string returned by QMetaMethod::signature() but this approach depends on some undocumented internals of toolkit and may be broken at any time by a new version of Qt.我查看了 qobject.h 文件,发现 SIGNAL() 和 SLOT() 宏只是在方法签名的开头添加了“1”或“2”字符,因此看起来应该可以添加相同的QMetaMethod::signature() 返回的字符串开头的字符,但这种方法取决于工具包的一些未记录的内部结构,并且可能随时被新版本的 Qt 破坏。

Does anybody know reliable way to connect signals and slots through their QMetaMethod reflection representation?有人知道通过 QMetaMethod 反射表示连接信号和插槽的可靠方法吗?

Edited: I've created suggestion in Qt issue tracker: https://bugreports.qt.io/browse/QTBUG-10637 If anybody also interested in this feature you can vote for this ticket there.编辑:我在 Qt 问题跟踪器中创建了建议: https : //bugreports.qt.io/browse/QTBUG-10637如果有人也对这个功能感兴趣,你可以在那里投票给这张票。

This has been fixed as of Qt 4.8.0:从 Qt 4.8.0 开始,这已得到修复:

https://bugreports.qt.io/browse/QTBUG-10637 https://bugreports.qt.io/browse/QTBUG-10637

Suppose we have a QObject* m_subject, and wish to connect the change-notification signal of a property to a propertyChanged() slot:假设我们有一个 QObject* m_subject,并且希望将属性的更改通知信号连接到 propertyChanged() 槽:

const QMetaObject* meta = m_subject->metaObject();
QMetaProperty prop = meta->property(meta->indexOfProperty("myProperty"));
if (prop.hasNotifySignal()) {
    QMetaMethod signal = prop.notifySignal();
    QMetaMethod updateSlot = metaObject()->method(
        metaObject()->indexOfSlot("propertyChanged()"));
    connect(m_subject, signal, this, updateSlot);
}

I successfully used this to make a QWidget subclass which finds all the properties of any QObject and creates a QLineEdit for each of them, with a connection to keep the QLineEdit updated whenever the corresponding property changes.我成功地使用它创建了一个 QWidget 子类,它可以找到任何 QObject 的所有属性,并为每个属性创建一个 QLineEdit,并通过一个连接来在相应的属性更改时保持 QLineEdit 更新。 (Because I didn't find a way to pass a propertyID value to propertyChanged() though, it was necessary to make a subclass of QLineEdit and implement propertyChanged() there. QSignalMapper didn't help, because all the properties are in the same object.) (因为我没有找到将 propertyID 值传递给 propertyChanged() 的方法,所以有必要创建 QLineEdit 的子类并在那里实现 propertyChanged()。QSignalMapper 没有帮助,因为所有属性都在同一个目的。)

It looks like there is no way to make it work without relying on internal implementation.看起来不依赖内部实现就没有办法让它工作。 If I were you, I'd submit feature request to Qt bug tracker , write a code that mimics current behavior SIGNAL/SLOT macros and add unit test that will fail when SIGNAL/SLOT behavior changes.如果我是你,我会向Qt bug tracker提交功能请求,编写一个模仿当前行为 SIGNAL/SLOT 宏的代码,并添加当 SIGNAL/SLOT 行为改变时将失败的单元测试。

There might be a simpler solution to the problem you're trying to solve: describe what exactly are you trying to do without any implementation details.对于您要解决的问题,可能有一个更简单的解决方案:在没有任何实现细节的情况下描述您到底要做什么。

Thanks to MBack, I now use metamethods to connect my view to my model's properties dynamically for MVVM or MVC pattern.感谢 MBack,我现在使用元方法为 MVVM 或 MVC 模式将我的视图动态连接到模型的属性。 In order to respect DRY, a boilerplate is required with something like this :为了尊重 DRY,需要一个样板文件,如下所示:

 void MyClass::connectSignalToSlot(QObject* sender, std::string signalName, QObject* receiver, std::string slotName)
 {
    int sigIdx = sender->metaObject()->indexOfSignal(signalName.c_str());
    auto signal = sender->metaObject()->method(sigIdx);
    int slotIdx = receiver->metaObject()->indexOfSlot(slotName.c_str());
    auto slot = receiver->metaObject()->method(slotIdx);
    connect(sender,signal,receiver,slot);
 }

void MyClass::connectPropertyChangedToSlot(QObject* sender, std::string propName, QObject* receiver, std::string slotName)
{
   int sigIdx = sender->metaObject()->indexOfProperty(propName.c_str());
   auto signal = sender->metaObject()->property(sigIdx ).notifySignal();
   int slotIdx = receiver->metaObject()->indexOfSlot(slotName.c_str());
   auto slot = receiver->metaObject()->method(slotIdx);
   return connect(sender, signal, receiver, slot);
}

If signature method is public in QMetaMethod then the result shouldn't be broken by trolls and it's safe to use it (documentation says nothing about "dangers" when using QMetaMethod::signature method).如果签名方法在 QMetaMethod 中是公开的,那么结果不应该被巨魔破坏并且使用它是安全的(文档没有说明使用 QMetaMethod::signature 方法时的“危险”)。 I think you can safely use it.我认为你可以安全地使用它。 Just to be sure, what version of Qt you are using right now ?可以肯定的是,您现在使用的是哪个版本的 Qt?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM