Connect in derived class to base class slot
-
Hello,
I have a class 'mainwindow' that manages all the GUI stuff and a class 'lending_system' that is supposed to do all the behind the scene things. The class mainwindow needs access to a lot of functions and Data of the class lending_system so I've decided to
let the class mainwindow inherit from lending_systems. I'm not sure if doing that makes any sense but I guess it gives you the ability to manage all the background stuff without being dependent on the GUI. The issue is that I'm trying to connect a button click (defined in the ctor of mainwindow) to a slot inside lending_system but it doesn't seem to find it.class lending_system{ protected: QList<medium*> medlist; //saves all medium objects QList<person*> perlist; //saves all person objects void read_medium(); //loads mediums from file into QList void read_person(); //loads persons from file into QList void write_medium(); //saves mediums from QList into file void write_person(); //saves persons from QList into file public: lending_system(); protected slots: void delete_person(unsigned int id); //deletes person from list };
class mainwindow: public QMainWindow, public Ui::MainWindow, public lending_system{ Q_OBJECT private: lending_system lend; void create_person_table(); public: mainwindow(QMainWindow *parent=0); ~mainwindow(); };
In the constructor of the mainwindow class there is the line:
connect(btn, SIGNAL(clicked()), this, SLOT(delete_person(perlist[i]->get_id())));
It compiles fine but when executing i get:
QObject::connect: No such slot mainwindow::delete_person(perlist[i]->get_id()) QObject::connect: (receiver name: 'MainWindow')
I hope my question isn't too dumb, I'm very new to QT.
Thanks for any help.
-
This is an old-style Qt connect
connect(btn, SIGNAL(clicked()), this, SLOT(delete_person(perlist[i]->get_id())));
The second and fourth arguments should the function signature of the signal or slot. This establishes a connection between objects, it does not send data, that happens when the signal is emitted.
This old-style connect should look like:connect(btn, SIGNAL(clicked()), this, SLOT(some_slot_in_your_class()));
and you need to put logic to do something in the slot some_slot_in_your_class() you have yet to define. Note that the signal clicked() does not send a parameter, and the new slot will not receive one, so you need to work out which person to delete some way.
Had you used new-style connects this would have failed at compile time.
There are other unusual things about this design:
- Class lending_system is not a QObject so it will not support signal/slots.
- Your code is saying that class mainwindow is-a lending_system. Is it really, or does it just know about a lending_system to operate on it?
- It is very unusual that a Designer generated UI would be publicly inherited, this should normally be private.
-
@ChrisW67
Thank you very much for your answer.
I misunderstood how slots work I thought it was just like a normal function."Your code is saying that class mainwindow is-a lending_system. Is it really, or does it just know about a lending_system to operate on it?"
mainwindow is something different from lending_system. I inherited it from lending_system just to be able to use all functions and also protected contents of lending_system without having to explicitly create a lending_system object. I realize that this
doesn't make a lot of sense and is not how inheritance should be used. I could either put everything in mainwindow or create an object of lending_system inside mainwindow and just work with that. I think I will do the latter one. About that, I have a c++ question. In mainwindow I would have to access a Qlist that is inside the lending_system object. I could do that in 3 ways and I'm not sure what the best or standard way is.- write a getter function get_list_at(i) that just does return list[i] and another getter function for the list size
- write a getter function that returns a pointer to the list which would allow me to directly work on it using [i] and .size()
- make the list public
Which one should I pick?
"It is very unusual that a Designer generated UI would be publicly inherited, this should normally be private."
Thanks for pointing that out. I followed a pretty old pdf to get started and just used the example to get started. I'm not sure why they did it that way.I just found out about QSignalMapper. I think that would be the best way to tell the delete function which entry to delete.
I will check out the new-style connects.
Thank you for your help.
-
@Lynix
If you change over to new styleconnect()
s, a further advantage is that you can use C++ lambdas for slots. They allow you to write the slot code you showed "in-line". They also allow passing parameters from the calling code to the slot. So your example might read something like:connect(btn, &QPushButton::clicked, this, [this, i]() { delete_person(perlist[i]->get_id()); });
Once you use lambdas to pass parameters the need for
QSignalMapper
disappears. That is much more limited in what you can pass/do than lambdas, and there is simply little point in using it these days as lambdas can do everything it does plus a variety of other things.