Rob
Rob

Reputation: 78748

Closing a QMainWindow on startup?

I have a Qt application that uses a QMainWindow-derived class for the main UI. On startup I want to make some security checks and, if they fail, display a message to the user and close the main window. Currently I make these checks in the QMainWindow constructor, but if I call the close method, nothing happens and the application continues to run. For example:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setupUi(this);
    ...
    if (checkFails())
    {
        QMessageBox::warning(this, tr("Error"), tr("You cannot run this app"));
        // This has no effect
        close();
    }
}

Alternatively I could make the checks in the main function but then I lose the ability to display a language-specific message box (the tr macro only works in a QObject-derived class by the looks of things.)

Any ideas on how to close the main window on startup or make the tr macro work outside of a QObject derived class?

Upvotes: 16

Views: 6662

Answers (4)

Phil Tresadern
Phil Tresadern

Reputation: 31

Most applications start up in three steps: 1) construct the window; 2) show the window; 3) start the event loop. You can make steps 2 and 3 conditional on the success of step 1 by adding a flag, whose value is set by the window constructor, to the window class:

Window class:

class myMainWindowClass : public QMainWindow
{
    Q_OBJECT
public:
    myMainWindowClass()
    : isFinished_(false) { if (error) isFinished_ = true; } // constructor

    bool isFinished() const { return isFinished_; }
private:
    bool isFinished_;
} 

Application code:

int main()
{
    myMainWindowClass main_window(); // Step 1

    // Finish early if isFinished flag is set
    if (main_window.isFinished())
      return 0;

    main_window.show(); // Step 2
    return a.exec(); // Step 3
}

This should also avoid any flicker as the application will end before the window is show()n.

Upvotes: 3

Ton van den Heuvel
Ton van den Heuvel

Reputation: 10548

The event loop needs to be running before you can successfully close the main window. Since you probably first construct a window, and then start the event loop the close() call has no effect. Try the following solution instead:

QTimer::singleShot(0, this, SLOT(close()));

The QTimer::singleShot() will fire as soon as an event loop has been started, and subsequently calls the close() method on your application main window.

The above solution will probably cause your main application window to be visible for a short period of time, causing unwanted flickering.

A cleaner solution should perform the security checks prior to constructing the main window. Since tr() is also available as a static method on QObject, this can be done from the main function.

Upvotes: 30

Ali Lown
Ali Lown

Reputation: 2341

Have you tried first hide()ing the window (this should occur anyway when close() is called) to see if this then allows close() to destroy the window.

If this does not work, you could always try destroy(true, true)ing the window along with any sub-windows.

Upvotes: 0

Mathias Soeken
Mathias Soeken

Reputation: 1313

tr is a public static member of QObject. You should be able to call QObject::tr("Error") in your main function.

Upvotes: 2

Related Questions