0

I have a complex widget on the screen which is visible. By pushing a button a dialog appears but parts of the original widget is still visible. When closing the dialog I would like to refresh some data of my particular widget ... but this widget does not know anything about that dialog. Is there any event I can check for this purpose ? Or any other way to get to know when the dialogs closed ?

First I used

virtual void QWidget::showEvent( QShowEvent* event );

but it is not called when the parts of the widget is already visible.

EDIT I'm sorry but I wasn't precise enough. When I wrote complex, I meant that I have a main window, which has a child widget which also has child widget and so on (for about file level). That lowest level child widget initiates the opening of the dialog. The other widget which needs the closing event of this dialog is also an embedded widget but somewhere else in the application. When I wrote sending the signal through many classes I meant this. In this case if want to notify my final widget I have to connect the closing signal from my source widget to several intermediate widgets which does not even interested in that signal. I also didn't want to (and can't) connect these signal/slot in the main window because of the mentioned structure. In this is there any advice ?

p.i.g.
  • 2,815
  • 2
  • 24
  • 41
  • I think it would be better to let the widget know about that dialog, maybe have a slot that is connected to the dialog's `finished` signal – Mike Jul 15 '16 at 17:06
  • @Mike It is not possible. It's a very complex form with lot's of widgets. One of them creates the dialog. I don't think that it would be a good idea to send the signal through many objects just for this purpose. – p.i.g. Jul 15 '16 at 17:55
  • That lowest level child widget can have a signal that you connect to a signal in the top-level widget (yes, you can do that). The number of layers between the top and the child doesn't matter. All you need is two signals and one connect statement. "I [...] can't connect these signal/slot in the main window because" But you can! See e.g. [this question](http://stackoverflow.com/q/38251956/1329652). I don't know how else to prove it to you that it's trivial - please show some self-contained code; generate childs manually without a `.ui` file to keep it simple here. – Kuba hasn't forgotten Monica Jul 18 '16 at 13:43

1 Answers1

2

send the signal through many objects just for this purpose

There's no such thing as sending a signal "through" objects unless you insist on manually threading it through a bunch of them. So this doesn't make much sense unless you explain why you want to "thread" the signal through many objects ("threading" as in a string through a needle, not as in a processing thread).

A signal-slot connection has two endpoints. All you need is:

  1. A signal at the dialog.
  2. A slot at the supercomplex widget.
  3. A connection set up outside of both of them. To make life simple, both the widget and the dialog could be instantiated in main(), and a connection set up before anything even appears on the screen.

The dialog signal you're looking for is simply QDialog::finished, if you have a properly designed dialog. Otherwise, use an EventSignaler of some sort to convert a QEvent::close to a signal.

The slot in the supercomplex widget should be e.g.:

Q_SLOT void refreshSomething();

Its signature/name shouldn't refer to the fact that some dialog was closed: that's coupling the API too much to the external detail of some dialog being there. The slot should get the dialog to update/refresh what you need. The reasons for invoking it are irrelevant to the widget.

Inside the widget, the slot's implementation should most likely simply call update() on one or more subwidgets, perhaps with a relevant region - if you wish to, you can have the region as an optional slot parameter.

See this question about how to forward signals or slots inside of a complex composite class that contains many objects. It's supposed to be very simple; if it's not you'll have to edit the question to indicate why it's complex for you.

At the simplest, with the most decoupled code - where the dialog knows nothing about the widget, and vice versa - as it should be, you can have:

class Dialog : public QDialog { ... };
class Widget : public QMainWindow { 
  Q_OBJECT
  Q_SIGNAL void showDialog();
  Q_SLOT void refreshSomething();
  ...
};

int main(int argc, char ** argv) {
  QApplication app{argc, argv};
  ...
  Widget widget;
  Dialog dialog;
  QObject::connect(&widget, &Widget::showDialog, &dialog, &QWidget::show);
  QObject::connect(&dialog, &QDialog::finished, &widget, &Widget::refreshSomething);
  widget.show();
  return app.exec();
}
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313