[Solved] Events between loose coupled objects
I was wondering which way is the best to let loose coupled object communicate.
I want to let my object update the status bar in the mainwindow.
I have used PRISM in WPF applications to help me to do this. In PRISM I can create a EventAggregator, where object either can subscribe to a event or publish the event, this way I can still have loose coupling between objects.
Which way is the best in Qt ? Do I make my own events or do I create my own signals and slots ?
Signals and slots are the way to go. In general you do not create your own event.
In Signals and Slots the one always need to know about the other... so the loose coupling is gone. Am I misunderstanding something ?
[quote author="DarkRoast" date="1298224984"]In Signals and Slots the one always need to know about the other... so the loose coupling is gone. Am I misunderstanding something ?[/quote]
That's of course wrong.
The sender (object that emits a signal) kind-of "broadcasts" it's status change. In your old architecture the object would create an event.
The receiver (object whose slot is connected to a signal) listens to the messages the connected object emits as a signal. In your old architecture it would be a subscriber to the events.
The sender does not need to know about any of the receivers (in kind of application logic, that you write! The internals do not bother you!)
The receiver, of course, knows about the sender; at least it knows the kind of message that is sent to it, as well as in your old architecture the listener would know about the event it has to subscribe to.
Thanks for your answers guys.
In my case I solved it like this:
I have a pure abstract class
@class CreateMainView : public QObject
virtual QLayout* GetMainView() = 0;
void UpdateStatusBar(const QString &message) const;
So all objects who inherit from this class have the opportunity to emit the signal UpdateStatusBar.
In my MainWindow class I do this:
@ CreateMainView *mainView = new View();
QWidget *widget = new QWidget(); widget->setLayout(mainView->GetMainView()); QLabel *statusLabel = new QLabel(""); this->statusBar()->addWidget(statusLabel); connect(mainView, SIGNAL(UpdateStatusBar(const QString &)), statusLabel, SLOT(setText(const QString &))); this->setCentralWidget(widget);@
So whenever some object emits the signal UpdateStatusBar the QLabel setText slot is activated.
Is this a "solid" way to do this ?
Yes, that's perfectly ok!
Indeed, that's exactly how the Trolls make things in the item model and view classes (using pure abstract base classes too).
Just a side note: It's enough to call
connect(mainView, SIGNAL(UpdateStatusBar(QString)), statusLabel, SLOT(setText(QString)));
That's the normalized form of the signatures when in use with the connect method. Your version is ok too, but you will have a slight performance gain with the normalized form.
Regarding the message in the main window: you might consider "QStatusBar::showMessage() ":http://doc.qt.nokia.com/4.7/qstatusbar.html#showMessage for displaying the messages with a timeout. In that case you must connect the UpdateStatusBar signal to a hand crafted slot in your main window class, because you cannot set an argument in the connect statement (i.e. you cannot use SLOT ( showMessage( QString , 5 ) ) ).
I will use the normalized signature in the connect method.
Thanks for the tip about implementing my own SLOT so I can use the statusBar::showMessage() with a time out.