0

I am a bit confused with Qt's onClick handling. I have a class which looks like this:

class DatabaseManager : public QObject
{
Q_OBJECT;
private:
    QSqlDatabase db;

public slots: 
    bool openDB(const QString& path);

};

And I have a class which handles the click on the button:

Click::Click(QWidget *parent) : QWidget(parent){
    QPushButton *create = new QPushButton("Create database", this);
    create->setGeometry(50,100,100,100);
    connect(create, SIGNAL(clicked()), this, SLOT(openDB("/home/peter/database.db")));
}

main.cpp

int main(int argc,char **argv){
    QApplication *app = new QApplication(argc, argv);
    QPushButton btn;

    DatabaseManager db;
    btn.move(300,300);
    btn.resize(250,250);
    btn.setWindowTitle("Dibli");
    btn.show();
    return app->exec();
}

How could I tell to the click handler, that I want to use a specific DatabaseManager object's openDB function? Because it doesn't create the file, if I click on it.

I've updated the code.

László Papp
  • 51,870
  • 39
  • 111
  • 135
erbal
  • 727
  • 3
  • 12
  • 32
  • What is the parent of `Click`? Why are you creating a *class* for handling a click? That doesn't make any sense at all. Also where is it that you are using `Click`? Because `Click` is not the parent of `DatabaseManager`, `QApplication` and `QPushButton` for sure. D'you have a *minimal understanding* of the problem? I don't think so. – Shoe Jul 27 '13 at 20:52
  • No, I don't really understand this slot signal thing, that's why I asked here. :) – erbal Jul 27 '13 at 21:16

2 Answers2

1

assuming your Click class derives from QObject, you should add a slot

public slots:
 void onClick() { openDB("/home/peter/database.db"); }

and connect that:

connect(create, SIGNAL(clicked()), this, SLOT(onClick()))

edit Since you show more code now, here is a different hint. Change main like

int main(int argc,char **argv){
    QApplication *app = new QApplication(argc, argv);
    QPushButton btn;

    DatabaseManager db;
    db.path = "/home/peter/database.db";
    QObject::connect(&btn, SIGNAL(clicked()), &db, SLOT(openDB()));

    btn.move(300,300);
    btn.resize(250,250);
    btn.setWindowTitle("Dibli");
    btn.show();

    return app->exec();
}

and

class DatabaseManager : public QObject
{
Q_OBJECT;
private:
    QSqlDatabase db;

public:
    QString path;

public slots: 
    bool openDB();

};

Note I added a member variable (db.path) to DatabaseManager, and changed the slot openDB removing the argument. That's because the button' signal cannot provide the string. The easier way then is to make it available in the class.

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • 5
    He also forgot the `Q_OBJECT` macro in the class definition. Without it, signals/slots might not work. Also, due to a glitch in qmake, when adding the Q_OBJECT macro to an already compiled class, you need to do a distclean and run qmake again, so you might want to add that too :-) – Nikos C. Jul 27 '13 at 14:10
  • @NikosC. you're true, but he will need anyway another slot to be able to pass the name' string – CapelliC Jul 27 '13 at 14:15
  • 1
    Q_OBJECT is always needed when subclassing QObject and using signals and slots. It *has* to be there. – Nikos C. Jul 27 '13 at 14:17
  • I've edited the code, but if I try to run it, I get this message: Object::connect: No such slot QApplication::DatabaseManager::openDB("/home/peter/Dropbox/C++/Qt/sql/database.db") Object::connect: (receiver name: 'myapp') – erbal Jul 27 '13 at 20:28
  • Works like a charm! Thank you very much! I guess I get how this slot signal stuff works :) – erbal Jul 28 '13 at 07:35
  • You're welcome ! SIGNAL/SLOT it's a very useful and practical programming construct. See for instance [this](http://prolog-in-the-wild.blogspot.com/2013/07/a-trick-for-qt-interthread-communication.html) handy way to perform calls between threads... – CapelliC Jul 28 '13 at 07:45
0

You cannot call the specific argument instance in the connect function call.

connect is processed by the MOC - meta object compiler - and add some magick to all object that has the macro Q_OBJECT. You have to call a function inside the connect in which you specify only the argument it will receive. (And if they are non qt-object you have to register them with qRegisterMetaType<MyDataType>("MyDataType"); but this is a different story).

So, remember, every time call:

connect(sender, SIGNAL( event() ),
        receiver, SLOT( onEvent() ))

and then:

void onEvent() {
    mycomplexoperation( ... )
}

EDIT:

thank to Riateche comment, I have to specify that you need qRegisterMetaType<MyDataType>("MyDataType"); with all object not listed in this list. QString not inherits from QObject but could be used in signal/slot system without registration. and thanks to Frank Osterfeld comment I have to add that only for queued signal/slot connections the registration is needed (I didn't know that)

thankd to

Community
  • 1
  • 1
nkint
  • 11,513
  • 31
  • 103
  • 174
  • "And if they are non qt-object you have to register them with qRegisterMetaType" - incorrect. I don't quite sure what you mean by "qt-object", but there are non-`QObject`s (e.g. `QString`) and even non-objects (e.g. `int`) that can be used without registration. Registration must be done for types not listed in [this list](http://harmattan-dev.nokia.com/docs/library/html/qt4/qmetatype.html#Type-enum). – Pavel Strakhov Jul 27 '13 at 15:00
  • One can use any types as signal/slots arguments without registration. Only for *queued* signal/slot connections the registration is needed. – Frank Osterfeld Jul 27 '13 at 22:33
  • really? I didn't kwno that. Do you mean `Qt::QueuedConnection` – nkint Jul 28 '13 at 09:28