在Qt中创建动态插槽

时间:2011-04-19 16:17:01

标签: qt dynamic signals-slots

我正在尝试动态创建插槽并连接它们。我能够动态创建pushButtons并将它们与现有插槽连接。但是,如果我有一个具有一些成员函数的类,并且我想将这些函数用作插槽,该怎么办?

从一般的角度来看,我想创建一个模板,用于在给定函数指针的情况下生成槽。这允许我们在不改变现有代码的情况下创建插槽,而不必使用MOC重新编译。 如果这没有意义,请告诉我。谢谢。

-CV

2 个答案:

答案 0 :(得分:11)

它确实很有意义。我认为QSignalMapper不是你想要的。如果你的函数没有参数,那么这样就足够了:

class SlotForwarder : public QObject
{
    Q_OBJECT

public:

    typedef void (*Function)(); // or whatever. I never get this syntax right...

    SlotForwarder(Function function, QObject* parent = 0) 
        : QObject(parent)
        , m_fptr(function)
    {}

public slots:

    void forward()
    {
        m_fptr();
    }

private:

    Function m_fptr;
};

为要封装的每个函数创建一个,并像往常一样连接到forward


现在,如果他们有参数,也许这篇Qt季刊文章可能会有所帮助。

Dynamic Signals and Slots by Eskil A. Blomfeldt

该技术涉及自己重新实现qt_metacall方法。该方法有这个签名:

int QObject::qt_metacall(QMetaObject::Call call, int id, void **arguments)

呼叫是一种metacall:插槽,信号,属性读取或写入等。每个插槽都有 id 。参数在 arguments 数组中打包(按值或作为指针)。阅读moc生成的代码是理解它是如何工作的好方法。

有关原始函数签名的数据仅在编译期间可用,但在运行时解析插槽。由于这种不匹配,您需要将函数包装到模板适配器类型中,该类型为qt_metacall的实现提供一个常量接口,并将arguments数组转换为函数可以理解的内容(参见Python) unpack运营商)。 Boost.Signals就是那种template hackery

答案 1 :(得分:3)

继承andref的代码,以便将任何成员函数用作插槽

    class SlotForwarder : public QObject
    {
        Q_OBJECT

    public:

        typedef void (*Function)();

        SlotForwarder(Function function, QObject* parent = 0) 
            : QObject(parent)
            , m_fptr(function)
        {}

    public slots:

        void forward()
        {
            m_fptr();
        }

    private:

        Function m_fptr;
    };

    int main(){
      QApplication a(argc, argv);
      MyClass myClassObject; //contains a function called MemberFunc
      //create a slotforwarder object so 
      SlotForwarder *memberFuncSlot = new SlotForwarder (std::tr1::bind(&MyClass::MemberFunc, &myClassObject));
      QObject::connect(ui.button,SIGNAL(clicked()),memberFuncSlot,SLOT(forward());
    }