2

I'm trying to display a QMessageBox through calling its show function in a lambda function like the following:

connect(ui->graphButton, &QAbstractButton::clicked, [](void){
        QMessageBox message;
        message.setText(tr("Graphing button clicked"));
        message.show();
});

However, upon clicking the graphButton, the QMessageBox window appears only momentarily before disappearing. How can I fix this?

IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
edition
  • 638
  • 14
  • 31

2 Answers2

4
message.exec();

to execute it.

Full code :

connect(ui->graphButton, &QAbstractButton::clicked, [](void){
        QMessageBox message;
        message.setText(tr("Graphing button clicked"));
        message.exec();
});

show only set the visibility status of the widget : http://doc.qt.io/qt-4.8/qwidget.html#show http://doc.qt.io/qt-4.8/qwidget.html#visible-prop while exec has the desired behavior http://doc.qt.io/qt-5/qmessagebox.html#exec

You do not need to use show, because it is the default visibility. Use it when you disabled the visibility of a widget to enable it again.

Boiethios
  • 38,438
  • 19
  • 134
  • 183
  • I think -1 because you should not call `message.exec()` – IAmInPLS Apr 13 '16 at 09:32
  • He just wants to display a debug message, I think. So the message box must be executed. I tried with Qt Creator : it displays the message and quits when I clicked on OK. Is it not the desired behavior ? – Boiethios Apr 13 '16 at 09:34
  • @Morovaille Perhaps you could explain why the QMessageBox window is still visible after `exec` is called? – edition Apr 13 '16 at 09:34
  • "exec" is legit : http://doc.qt.io/qt-4.8/qmessagebox.html#exec . Why should it not be called @Alexis P.? – Ahmet Ipkin Apr 13 '16 at 09:41
  • My bad, didn't read the question well. I'm not the one who gave a -1 by the way – IAmInPLS Apr 13 '16 at 09:43
  • @AhmetIpkin [This is why](https://blogs.kde.org/2009/03/26/how-crash-almost-every-qtkde-application-and-how-fix-it-0). – thuga Apr 13 '16 at 10:30
  • 1
    *You should not use show, because it is the default visibility. Use it only when you disabled the visibility of a widget to enable it again.* Not true. You can use `show` to show any widget for the first time. It doesn't have to be hidden first. – thuga Apr 13 '16 at 10:34
  • @thuga This is not a reason why `exec` shouldn't be used; it is an explanation on why you must not create a QMessageBox on stack and instead, create using smart pointers.... – Ahmet Ipkin Apr 13 '16 at 10:35
  • @AhmetIpkin It is exactly the reason why exec should be used with care. Storing `QMessageBox` in a smart pointer makes no difference. Imagine a situation where `this` is destroyed before `exec` returns. Then after `exec` you try to access some member of `this`. This is explained in the link I posted. Also, just to clarify, I'm not saying you should definitely not use it here. – thuga Apr 13 '16 at 10:40
  • @thuga you are right about `show`, I edited, thanks. – Boiethios Apr 13 '16 at 10:48
  • @thuga ... and how doesusing "show" instead fix this problem ? By the same scenario, "this" can be destroyed even when u are actually doing some other stuff in this lambda-functor. The problem you described is not of `exec`'s or `show`'s; rather concurrent access problem in modal windows - which is a general 'consideration case' for all multi-access/concurrent designs. – Ahmet Ipkin Apr 13 '16 at 10:49
  • @AhmetIpkin I'm talking about using `exec` in general, not just in this specific scenario. As you saw in the link, there are no lambda functions there. The difference with `show` is that it doesn't create an event loop and wait for it to return from there. It just shows the widget and moves on. – thuga Apr 13 '16 at 10:52
  • @AhmetIpkin [See this question](http://stackoverflow.com/q/35561182/2257050) if you need more clarification. – thuga Apr 13 '16 at 11:09
  • @thuga if we cannot using nested loops, how to display a modal dialog ? – Boiethios Apr 13 '16 at 11:12
  • @thuga Oh, now I see what you are referring: you are against the "message loop" exec creates; not the concurrency problem. Sorry; you are right on that one :) – Ahmet Ipkin Apr 13 '16 at 11:12
  • @Morovaille You can set the window modality with [setWindowModality](http://doc.qt.io/qt-5/qwidget.html#windowModality-prop) method. – thuga Apr 13 '16 at 11:48
  • @thuga I know, but how to display it and wait for user ? – Boiethios Apr 13 '16 at 11:49
  • Check my answer below @Morovaille. It does it. – Ahmet Ipkin Apr 13 '16 at 11:53
  • @Morovaille Well the idea is to design the GUI side of your application so you don't have to wait for anything. You emit a signal when user interacts with the message box and then handle the response in a slot. – thuga Apr 13 '16 at 12:22
-1

Use QMessageBox.setModal to set the message box to "Modal" mode (that is, it blocks the execution until it is done working) and then use "open" method to show the messagebox.

connect(ui->graphButton, &QAbstractButton::clicked, [](void){
    QMessageBox message;
    message.setText(tr("Graphing button clicked"));
    message.setModal(true);
    message.open( ... );
});
Ahmet Ipkin
  • 882
  • 1
  • 10
  • 20
  • That’s wrong, setModal(true) doesn’t block any execution (it just disables the other windows for user input), neither does open(), so the message box is still destroyed right away after open(), so the message box never becomes visible. To make it work, one has to either use exec() or create the messagebox on the heap/make it a class member so it survives the block it’s created in. – Frank Osterfeld Apr 13 '16 at 12:24
  • That's about modality, still modality of dialogs has nothing to do with whether the execution is blocked or not. Try your code (I did) - it doesn't work as the dialog is destroyed right away, being created on the stack. – Frank Osterfeld Apr 13 '16 at 12:56
  • Yep, my mistake there. Didn't test the code, and assumed that the behaviour is the same as C# / Delphi . – Ahmet Ipkin Apr 13 '16 at 12:56