Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing a QMainWindow on startup?

Tags:

c++

qt

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?

like image 607
Rob Avatar asked Mar 01 '10 15:03

Rob


3 Answers

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.

like image 54
Ton van den Heuvel Avatar answered Nov 07 '22 10:11

Ton van den Heuvel


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.

like image 3
Phil Tresadern Avatar answered Nov 07 '22 10:11

Phil Tresadern


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

like image 2
Mathias Soeken Avatar answered Nov 07 '22 12:11

Mathias Soeken