0

Getting right to it I have a MainWindow and a dialog window which is executed if a condition is met but the problem is I can't get the app to quit if the cancel button from the dialog window is clicked. I've tried putting qApp->quit() in the slot function for the cancel button. I've tried connecting the cancel button slot to the predefined close slot for the MainWindow object via a clickme() signal from the dialog class. (as shown below)

qt application does not quit I read the answer to this question which I think got me close because it made me realize that I can't quit the app before showing the MainWindow but making that change didn't solve the problem. I even tried to explicitly emit the clickme() signal from cancel button slot but that actually caused the OS to throw a signal which threw an error at me saying "the inferior stopped because it received a signal from the operating system signal name: SIGSEGV signal meaning: segmentation fault"

Here's my code:

Notice warning; // this is the object for the dialog window also all of this code is in main.cpp
 warning.setModal(true);
    QObject::connect(&warning, SIGNAL(clickme()), &warning, SLOT(on_Cancel_button_clicked()));
    QObject::connect(&warning, SIGNAL(clickme()), &w, SLOT(close()));
    warning.exec();

Also before that code is

MainWindow w;
w.show();

Also while writing this question I tried this

QObject::connect(&warning, SIGNAL(clickme()), qApp, SLOT(quit()));

But that still didn't work. If you need more info just let me know.

Update: I'm starting to think that the reason I'm having so much trouble with this connect signal/slot function is because it's not designed to connect two windows of two different classes and I should rework my app to do everything from the MainWindow class which is a shame because when I picture a GUI program I picture multiple windows connected to each other regardless of whether or not the object representing each window is from the same class as the others yet I have such a hard time trying do that with the QT framework when it comes to trying to connect objects of different classes.

Update: please forgive me. I assume that the code that I originally thought was the answer would work and took a break from working on the program before actually testing out that code. Going back to it now I discovered that it doesn't work. The code I'm referring to is the following

QMessageBox msg;
    msg.setText("Continue?");
    msg.addButton(QMessageBox::Yes);
    msg.addButton(QMessageBox::No);
    QObject::connect(&msg, &QMessageBox::rejected,
                     &app, &QApplication::quit); // this line doesn't work for me and I don't know why
    QObject::connect(&msg, &QMessageBox::accepted, [&dlg]{
      (new QLabel("I'm running")).show();
    });
Community
  • 1
  • 1
codehelp4
  • 132
  • 1
  • 2
  • 15
  • It's not clear what your question is (understood the first line, but then I was lost). AFAIK, there is no `clickme` signal on `QDialog` - unless you derived from `QDialog` and emitted your own signal. Typical idiom for dialogs is you process, say the cancel button's signal, `&QAbstractButton::clicked` and invoke `&QDialog::reject` slot. It is likely that not processing the one of `QDialog`'s 3 signals, `accepted, rejected, finished` is your problem. I would try that first and see if the dialog box goes away. Then you're home free. – NameRakes Jan 09 '17 at 02:58
  • The dialog window does close but the app still continues to run. (I want it to quit) The reason I used clickme() is because it worked for a version of the program that I was working on before. I tried using clicked from QAbstrationButton but that didn't work either. I think I should reiterate that I'm trying to get the entire app to quit from the dialog window. – codehelp4 Jan 09 '17 at 04:05
  • When you say your app continues to run, you mean to say the main window? And also which widget has `clickme()` signal/action? The clean way to respond to closing of dialog window is to process based on the value returned: `accepted`, `rejected` or `finished`. – NameRakes Jan 09 '17 at 08:58
  • Yes main window as well as all the code I have in the function main. I've changed the signal to clicked. I'm trying to connect the signal of clicking the cancel button in the dialog to triggering the app to quit. – codehelp4 Jan 09 '17 at 09:25
  • 1
    Does the `MainWindow` have the attribute `Qt::WA_QuitOnClose`? Try also with `warning.setAttribute(Qt::WA_DeleteOnClose);` – Tarod Jan 09 '17 at 10:29
  • Thanks I'll add those attributes but regardless of those the main window doesn't close hence my issue with the connect function calls. – codehelp4 Jan 09 '17 at 21:04
  • About your last update, I noticed the code is from the linked question. I tested the code and it didn't work. It's true the slot is never called. You can see the reason [here](http://stackoverflow.com/questions/25545652/qdialog-exec-can-not-exit-process/25549491#comment71980279_25549491) – Tarod Feb 23 '17 at 18:16
  • So the reason is because of a bug in qt that was never fixed. The answerer says in the comments there that they fixed it in the code they posted with QObject::connect(&msg, &QMessageBox::buttonClicked, onClick); which still didn't work for me. Also on a side note I'm puzzled as to why my question suddenly became downvoted for noticing this bug especially since that line of code that was supposed to be the fix doesn't work which isn't obvious in that post whereas being downvoted made me felt like I missed something obvious. – codehelp4 Feb 24 '17 at 04:17
  • When you say "which still didn't work for me", do you mean you don't see the label with the text when you click the `Yes` button? It is working in my case. – Tarod Feb 24 '17 at 06:03
  • No I mean that when I click the no button in the dialog window the program doesn't quit. The only thing that closes is the dialog window but the main program continues to run (for eample MainWindow doesn't close) – codehelp4 Feb 24 '17 at 07:37
  • I've just updated my answer. The example is working so if you click the no button, the application ends. Maybe you could post more code from your project if your problem continues. – Tarod Feb 24 '17 at 08:20

2 Answers2

0

QApp->quit(); should work. Remove warning.setModal(true); The dialog becomes modal when you call exec(). SetModal(true) should be used with show() according to Qt docs. So this may be causing your problem.

kn0w0n3
  • 169
  • 1
  • 13
  • commenting out warning.setModel(true) didn't fix the problem. I tired that both ways. 1. having qApp->close() be in the MainWindow closer() function I made. 2. having qApp with close() in the connect call itself.(as shown in last line of code I show in the question) – codehelp4 Jan 10 '17 at 08:23
0

I think I've found the problem.

Probably, you're calling exec() twice:

  1. To enter the QApplicationevent loop
  2. To execute the dialog.

Use show() instead of exec() for the dialog. You have an example below where you can check the signal/slot works well. In your application, you need the slot to close the window, but:

  1. With the line of code dialog.exec();, the app keeps running. This is your issue.
  2. With the line of code dialog.show();, the app stops.

By the way, I saw your last question update, but it is not correct. In fact, of course you can connect two different classes.

window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QApplication>
#include <QMainWindow>
#include <QAbstractButton>
#include <QDebug>
#include "dialog.h"

class Window : public QMainWindow
{
Q_OBJECT

public:
    Window()
    {
        dialog = new Dialog();
        dialog->setText("Continue?");
        dialog->addButton(QMessageBox::Yes);
        dialog->addButton(QMessageBox::No);
        auto onClick = [this]() {
            auto role = dialog->buttonRole(dialog->clickedButton());
            if (role == QMessageBox::NoRole) {
                qDebug() << "QMessageBox::NoRole";
                QApplication::quit();
            }
            if (role == QMessageBox::YesRole) {
                qDebug() << "QMessageBox::YesRole";
            }
        };

        QObject::connect(dialog, &QMessageBox::buttonClicked, onClick);

        dialog->show(); // this must be show(), not exec()
    }
    virtual ~Window() { delete dialog; }
private:
    Dialog *dialog;

public slots:
    void windowSlot() { qDebug() << Q_FUNC_INFO;
                        close();
                      }
};

#endif // WINDOW_H

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QMessageBox>

class Dialog : public QMessageBox
{
Q_OBJECT

public:
    Dialog() {}
    virtual ~Dialog() {}
};

#endif // DIALOG_H

main.cpp

#include <QApplication>
#include <QtGui>
#include "window.h"

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    Window window;
    window.setWindowTitle("window");
    window.show();

    return app.exec();
}

Update #1: a very interesting post.

Community
  • 1
  • 1
Tarod
  • 6,732
  • 5
  • 44
  • 50
  • I think you're correct I need to rework code to follow the thing you linked. Also I figured the connect function would be able to work like that which is why I couldn't figure out why it didn't seem to be working for me. Thanks. – codehelp4 Jan 10 '17 at 22:58