4

I'm currently working on a Qt project and I have some troubles with SLOTs. I want to pass a pointer to member function as an argument of a SLOT. To do this, I declared the SLOT in my class but when I do so, I get MOC error. I don't know if what I want to achieve is even possible.

An exemple of syntax for a class named MainFrame:

void slotAnswerReceived (QString answer, void (MainFrame::*ptr)(QString));

I don't have any connect anywhere, nothing using that function, and the only error I have is on this line above.

Thank you everyone for the help. I cannot find any solution on the web (but I found this article explaining SIGNAL and SLOT in depth if someone is interested).

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • Just a little question : why do you want to pass a pointer as argument ? – Thomas Ayoub Mar 24 '14 at 11:38
  • What error do you get? Possible, you forgot to call Q_DECLARE_METATYPE / qRegisterMetatype for your function pointer type? – Dmitry Sazonov Mar 24 '14 at 11:38
  • [debug/moc_MainFrame.cpp] Error 1. Don't heard about Q_DECLARE_METATYPE (I'll look). I know that I can put the declaration of this function in public and it works, but I can't use it as a SLOT because of that error. I'm using a QTcpServer and when I receive an answer I also got that pointer which gives me the next function to call. – user3429997 Mar 24 '14 at 14:11
  • I tried to put qRegisterMetaType("MainFrame"); but it says that compilation error: "QMainWindow is private". – user3429997 Mar 24 '14 at 14:46

1 Answers1

7
  1. Declare a typedef for that pointer-to-member type.

  2. Declare and register the metatype for that typedef.

  3. Only use the typedef - remember that moc uses string comparison to determine type equality, it has no C++ type expression parser.

An example follows. At the time a.exec() is called, there are two QMetaCallEvent events in the event queue. The first one is to c.callSlot, the second one is to a.quit. They are executed in order. Recall that a queued call (whether due to invokeMethod or due to a signal activation) results in posting of a QMetaCallEvent for each receiver.

#include <QCoreApplication>
#include <QDebug>
#include <QMetaObject>

class Class : public QObject {
   Q_OBJECT
public:
   typedef void (Class::*Method)(const QString &);
private:
   void method(const QString & text) { qDebug() << text; }
   Q_SLOT void callSlot(const QString & text, Class::Method method) {
      (this->*method)(text);
   }
   Q_SIGNAL void callSignal(const QString & text, Class::Method method);
public:
   Class() {
      connect(this, SIGNAL(callSignal(QString,Class::Method)),
              SLOT(callSlot(QString,Class::Method)),
              Qt::QueuedConnection);
      emit callSignal("Hello", &Class::method);
   }
};
Q_DECLARE_METATYPE(Class::Method)

int main(int argc, char *argv[])
{
   qRegisterMetaType<Class::Method>();
   QCoreApplication a(argc, argv);
   Class c;
   QMetaObject::invokeMethod(&a, "quit", Qt::QueuedConnection);
   return a.exec();
}

#include "main.moc"
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313