Best way to make 2 differents subclasses communicate
-
Hi,
Why not have your ConnectionWidget emit a signal with a QString parameter and connect it to the QMainWindow statusbar slot showMessage() ?
MainWindow.cpp
@
ConnectionWidget *connectionWidget = new ConnectionWidget;
connect(connectionWidget, SIGNAL(messageToShow(QString)), statusBar(), SLOT(showMessage(QString)));@Hope it helps
EDIT:forgot showMessage QString parameter
-
wrote on 11 Apr 2013, 11:08 last edited by
[quote author="SGaist" date="1365676850"]Hi,
Why not have your ConnectionWidget emit a signal with a QString parameter and connect it to the QMainWindow statusbar slot showMessage() ?
[/quote]Actually, this is what I did first. The thing is I want to handle general status like "Ready" and temporary status like "Field can't be empty", and when the temporary is cleared, I show back the last message. I have a QString attribute to store it in the MainWindow. If I connect directly the parent's statusBar, I have to implement the "last message" system in the children which is not logical for me.
Thank you anyway.
-
Field empty error should be shown directly besides your mandatory input, it would be clearer for the user.
As for managing temporary/constant message, if your temporary message are "time based" you can use showMessage(myString, myTimeoutValue). If it's a bit more complex you can either make a QStatusBar subclass and handle that there, make an object that is a "man in the middle" that handles that, or use your MainWindow for that purpose.
Hope it helps
-
wrote on 11 Apr 2013, 12:46 last edited by
This is the point, I want to know if there is a "common" or "classic" pattern for this sort of interactions.
Currently, here is what I have:
@// ConnectionWidget.hpp
signals:
void changeStatus(QString message, int timeout);@@// ConnectionWidget.cpp
connect(this, SIGNAL(changeStatus(QString, int)),
this->m_parent->statusBar(), SLOT(showMessage(QString, int)));
emit this->changeStatus("Ready", 0);@@ // MainWindow.cpp
if (timeout)
this->m_oldStatusMessage = this->statusBar()->currentMessage();
else
this->m_oldStatusMessage.clear();
this->statusBar()->showMessage(message, timeout);@The thing here is that the children have to connect themselves to the parent status bar, my question is more "is it a good way to do it" instead for example, make the parent listen to the children signals ? The correct way to make this. Parent listen child(ren), Children connect to parent, delegate, ...?
Thank you for your answers.
-
Make these connections in MainWindow.
ConnectionWidget should not care of where the signal is going. On the other hand MainWindow knows what to do with this signal so it's his job to do the connection.
This keeps your classes decoupled.
-
wrote on 11 Apr 2013, 13:11 last edited by
Here we are. If the MainWindow makes the connection itself, it means it has to know the type of the child.
As the "childs" are subclasses of QWidget, do I have to subclass QWidget to add the signals ? Then force MainWindow to only accept "MyOwnWidget *" by overloading "setCentralWidget" ?
I ask this because if I don't do this (which complicates my code) I don't know how to listen for the "setCentralWidget" to avoid trying to connect to empty centralWidget.
Thank you :)
-
wrote on 11 Apr 2013, 13:33 last edited by
well... didn't you say that connectionwidget is your subclass of QWidget, which is your centralWidget? If you trully are worried about this, you could check to see if QMainWindow::centralWidget() != 0, because "documentation":http://qt-project.org/doc/qt-4.8/qmainwindow.html#centralWidget says that it will return 0 when no widget has been set
-
wrote on 11 Apr 2013, 16:22 last edited by
[quote author="b1gsnak3" date="1365687201"]well... didn't you say that connectionwidget is your subclass of QWidget, which is your centralWidget?[/quote]
Hey, you're focused, I like it =PYes I did, my ConnectionWidget is a subclass of QWidget, it's intended to be a central widget but not the only one. That's why I'm stuck here. I have to find a way to let children handle the message easily.
Thanks anyway.
-
wrote on 15 Apr 2013, 06:40 last edited by
Ok. But be careful because setting a new central widget will delete the old one. As to your problem, please, if you can, explain again to me because I can't understand from bits and pieces xD
-
If you have multiple widgets that will go as "central widget", you might be interested by QStackedWidget. Have all your widgets in the stack and show the right widget at the right time.
-
wrote on 15 Apr 2013, 08:20 last edited by
[quote author="b1gsnak3" date="1366008052"]Ok. But be careful because setting a new central widget will delete the old one.[/quote]
Yup, thanks. I always @delete this->centralWidget();@
[quote author="SGaist" date="1366010452"]you might be interested by QStackedWidget.[/quote]
Unfortunately, I forgot about it and did something ugly, but really efficient for my case.I re-explain for b1gsnak3: I want a simple and easy system to change my centralWidget and listen to the child "changeStatus" to route it to statusBar()->showMessage(). I did it my way at the beginning (connection in children, bad), but someone (Objective-C dev) told me about the delegates but I wanted C++ dev advices.
Here is what I did:
I've created my own "AbstractWidget" which has a pure virtual slot (nextWidgetAction()), which what the children have to call when they've done their job (Database connection for example).
"nextWidgetAction()" must actually create a new widget, which is the next widget the parent have to show in its centralWidget, and emit the signal "widgetJobFinished(AbstractWidget *newWidget)".
The parent is listening to widgetJobFinished() and call setCentralWidget with the parameter.
I've overloaded "setCentralWidget()" in my MainWindow to take only "AbstractWidget *", to be able to pass it any of my subclassed widgets.
In "setCentralWidget(AbstractWidget *)", I delete "this->m_centralWidget;" (which is my subclassed current widget).
Then I call "QMainWindow::setCentralWidget(newWidget);" to set my new centralWidget, store it in my MainWindow and listen to the newWidget's slot "widgetJobFinished(AbstractWidget *)".
It's not really nice to do that way, but to combine a system where the MainWindow can't know in advance which "type" of widget it has to show when and change the statusBar() correctly, the best way for me was to initialize IN the children the following widget (for i.e.: "welcomeWidget" inits "databaseConnection" which inits "queryWidget") and obviously the widgets can't show backwards (the old are deleted) and there is no need.
What do you think about that ?
-
Isn't that some sort of QWizard you are writing ?
-
wrote on 15 Apr 2013, 08:29 last edited by
[quote author="SGaist" date="1366014252"]Isn't that some sort of QWizard you are writing ?[/quote]
Hum... Now you mention it, yes it is :/
But I don't need the ability to go backward, but except that, it could be a QWizard. -
wrote on 15 Apr 2013, 10:09 last edited by
1st. For your setCentralWidget I would do it like:
@
if(this->centralWidget() != 0) delete this->centralWidget();
@2nd. You could've used just one class, with an Enum of properties (which you set when you instantiate the properties) that would be your different types of action your widget needs to do and according to those properties create your widgets and call different methods (or use different constructors for each type of widget). And you would've had one big class instead of multiple ones.
-
wrote on 15 Apr 2013, 10:18 last edited by
-
I think you can delete multiple times "NULL" but not an already deleted pointer. So checking if NULL won't guaranty me to delete an allocated space. Anyway, I have the habits to do like this EVERY TIME, to be safe, and to be able to delete it again and again if I try to delete a pointer passed by a parent for example:
@ptr = new ...;
delete ptr;
ptr = NULL;@ -
I could do like that, but I wanted my MainWindow completely unaware of the children, as a QMainWindow would. So it means, every time I want a new widget, I just have to create it in the previous child and pass it in the SIGNAL. Then I don't need to modify the MainWindow class, and I will have multiple children because anyway, these children will have their own job and so their own class. Isn't it ?
-
11/16