One way to do that requires us to add to our MainWindow class a slot and the definition of a pointer to our dialog class:
class MainWindow : public QMainWindow
The class ctor would now initialize to NULL the pointer to the dialog and provide a connection from the Ui action to the slot in the main window class:
MainWindow::MainWindow() : QMainWindow(NULL), ui(new Ui::MainWindow),
connect(ui->actionSayHello, SIGNAL(triggered()), this, SLOT(sayHello()));
We say that the signal triggered() for the ui actionSayHello object is connected to this sayHello() slot. Now, when the user click on the Say Hallo menu item, the triggered() signal is emitted and, through this connection, the MainWindow::sayHello() slot for this object is called.
Our definition for the sayHello function would be something as:
if(dlgHello == NULL) // 1.
dlgHello = new DlgHello(this);
dlgHello->show(); // 2.
1. Lazy initilization for the dialog - the first time the function is called, the object is created. This is a modeless dialog, so we just create it once and show/hide it accordingly to user requests.
2. Actually, calling all three these functions on the dialog is a bit an overkilling. It would be cleaner to call just show() if the dialog is hidden, and otherwise raise() and activateWindow(). But if the dialog is not hidden, show() does nothing, so writing the code in this way save us to some extra-typing that wouldn't add any value to our function.