我正在尝试动态创建插槽并连接它们。我能够动态创建pushButtons并将它们与现有插槽连接。但是,如果我有一个具有一些成员函数的类,并且我想将这些函数用作插槽,该怎么办?
从一般的角度来看,我想创建一个模板,用于在给定函数指针的情况下生成槽。这允许我们在不改变现有代码的情况下创建插槽,而不必使用MOC重新编译。 如果这没有意义,请告诉我。谢谢。
-CV
答案 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());
}