Modal and modeless dialog boxes

When a dialog window pops up, you can’t operate other Windows unless you operate on it. This dialog box is called a modal dialog box. The converse is called a modeless dialog.

Modal dialog box

How are modal dialogs implemented in Qt? You need to use not only the QDialog class, but also exec().

As mentioned in Qt’s framework, exec() causes the program to enter a loop that does not end until the user performs an operation. Therefore, it is also needed to implement modal dialogs, and only when the user gives feedback to the dialogs can they proceed with subsequent operations.

Here are a few lines of code to see what a modal dialog is:

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget>
#include <QDialog>    // Implement the header that the dialog box must import
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // This part of the code is omitted
    QDialog *pDialog=new QDialog(this);
    pDialog->exec(a);// Notice that the QDialog object calls the exec method
    qDebug() < <"User has operated on the modal dialog box.";
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
Copy the code

Effect:

Since nothing is added to the dialog box, this is a simple dialog box, and nothing is printed in the console. Now we click “×” to close the dialog box. The effect is as follows:

You can see that the dialog box disappears and the main window appears, while the console prints “User acted on the modal dialog box”, meaning that the statement after the exec() method is executed after the user reacts to the modal dialog box.

Note: Why does the dialog box appear before the main window? Because the dialog box is defined in the constructor of the main window, including the exec method it calls, the main window appears only after its own constructor ends and the show method is called.

What if a modal dialog was defined in main.cpp? Here’s a look at the two cases:

#include "MainWindow.h"
#include <QApplication>
#include <QDialog>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QDialog *pDialog=new QDialog(a); pDialog->exec(a); MainWindow w; w.show(a);return a.exec(a); }Copy the code

Effect:

At this point, only the dialog is displayed, and then we click the Close button:

Click the close button before executing the statement following exec(). Therefore, this is when the main window is displayed.

Just now, we defined modal dialogs before the main window. What happens if modal dialogs are defined after the main window?

#include "MainWindow.h"
#include <QApplication>
#include <QDialog>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show(a); QDialog *pDialog=new QDialog(a); pDialog->exec(a);return a.exec(a); }Copy the code

Effect:

Although very paste (-_ – | |) or you can see, the modal dialog box is covered by the main window at the beginning, but immediately ran to the front. And there is no way to operate the main window behind without closing the dialog box.

Modeless dialog box

To implement modeless dialogs, simply change the exec() method to the show() method.

Click the “new” button of the menu bar will pop up a modeless dialog box function, the code is as follows:

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget>
#include <QDialog>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // This part of the code is omitted. PCreate is the pointer to the QAction object defined in the omitted code
    connect(pCreate,&QAction::triggered,[=](){
        QDialog mDialog;
        mDialog.show(a);qDebug() < <"1111";
    });
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
Copy the code

Effect:

You can see (?) When I click On New, there’s a dialog box that does appear,But then it disappeared. At the same time, the console also prints the contents of “1111”, indicating that modeless dialogs do not need to wait for user feedback before executing the code after the show() method.

But! Why did the dialog box disappear?

This is because the mDialog is defined on the stack and is also a local variable. When it leaves the function body, it is automatically reclaimed by memory, so it no longer exists and therefore disappears.

To solve this problem, the mDialog can be made a member variable of the main window class, or it can be dynamically allocated memory using the new keyword, so that it will only disappear when we manually free the memory using the delete keyword.

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget>
#include <QDialog>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // This part of the code is omitted. PCreate is the pointer to the QAction object defined in the omitted code
    connect(pCreate,&QAction::triggered,[=](){
        QDialog *mDialog=new QDialog(this);    // Dynamically apply for memory
        mDialog->show(a);qDebug() < <"1111";
    });
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
Copy the code

Effect:

So that’s where the dialog stays. When we close the main window, the dialog disappears. At this point, although we do not manually free memory by delete, since its parent element (the main window) is closed, the program ends and its destructor is called, so the destructors of all its children are also called and are destructed before the main window. [See: blog.csdn.net/weixin_4100…]

Note: One disadvantage of using dynamic memory allocation is that it only releases memory at the end of the program. If you click the “New” button too often, you will dynamically allocate memory multiple times, which also causes memory leak problems. Therefore, it is best to define the dialog box as a member variable of the main window class. Or, after dynamically allocating memory space, add a line of code that automatically frees memory each time a dialog box is closed.

QDialog *mDialog=new QDialog(this);         
mDialog->setAttribute(Qt::WA_DeleteOnClose);    // Reclaim memory while closing the dialog box
mDialog->show(a);Copy the code

Standard dialog and file dialog

Standard dialog box

In actual development, we often see the standard dialog box and file dialog box, what is the standard dialog box? Look at the picture:

Is that familiar? Standard dialogs are modal dialogs, but they are often not implemented directly because the buttons need to be artificially added. There is an easier way to implement the above style dialogs.

First, to implement standard dialogs, you need to introduce header files.

about()

The about method is used if you want to implement a dialog box that is often used in a program to describe software products to the user and only requires the user to click an “I know” button.

Call the About () function of the QMessageBox class, whose arguments are known from the help documentation as “parent”, “title”, and “content”.

#include "MainWindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QDebug>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QTextEdit>
#include <QDockWidget>
#include <QDialog>
#include <QMessageBox>    // The header file that must be imported to use the standard dialog box
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    PCreate is a QAction pointer variable defined in the ellipsis code
        connect(pCreate,&QAction::triggered,[=](){
            QMessageBox::about(this."create"."New");
        });
}
 
MainWindow::~MainWindow() {}Copy the code

Effect:

You can see that clicking the “New” button will bring up a modal dialog box titled “Create” with the content “New”.

P. :

Implementing the standard dialog with the following code looks the same.

connect(pCreate,&QAction::triggered,[=](){    
    QMessageBox pMessageBox;                  
    pMessageBox.about(this."haha"."hoho");    
    / / QMessageBox: : about (this, "create", "new");
});                                           
Copy the code

question()

If you want to implement a dialog asking the user whether to do something, you need to use the Question method.

Call the QMessageBox class’s question() function, whose arguments are known from the help documentation as “parent”, “title”, “content”, “value of first button”, “value of second button”, and “value of third button”. The second and third buttons default to 0, meaning that if they are not set, they are considered NoButton, meaning that there are no second and third buttons.

Here is the case where only the value of the first button is specified:

connect(pCreate,&QAction::triggered,[=](){                        
   QMessageBox pMessageBox;                                       
    pMessageBox.question(this."haha"."hahaha",QMessageBox::Yes);  
});                                                               
Copy the code

Effect:

Here is the case where three buttons are specified:

connect(pCreate,&QAction::triggered,[=](){                                                         
   QMessageBox pMessageBox;                                                                        
    pMessageBox.question(this."haha"."hahaha",QMessageBox::Yes,QMessageBox::No,QMessageBox::Cancel);
});                                                                                                
Copy the code

Effect:

Note: No more than three buttons, otherwise an error will be reported.

E:\Demo\QtDemo\BilibiliTest\06_QDialog\MainWindow.cpp:74: error: C2664: “Int QMessageBox::question(QWidget *,const QString &,const QString &, QMessageBox: : StandardButton, QMessageBox: : StandardButton) “: couldn’t get parameters of the 4” QMessageBox: : StandardButton “into” const QString &”

Here is the case where only the first three parameters are given and no button values are given:

connect(pCreate,&QAction::triggered,[=](){     
   QMessageBox pMessageBox;                    
    pMessageBox.question(this."haha"."hahaha");
});                   
Copy the code

Effect:

QMessage::question() returns an int, which returns the value of the button clicked by the user. For example, clicking Yes returns 16384 (0x4000), clicking No returns 65535 (0x10000). To deal with the user’s different choices. Such as:

connect(pCreate,&QAction::triggered,[=](){              
   QMessageBox pMessageBox;                             
    int ret=pMessageBox.question(this."haha"."hahaha"); 
    switch(ret){                                        
    case QMessageBox::Yes:                              
        qDebug() < <"The user clicked Yes";                           
        break;                                          
    case QMessageBox::No:                               
        qDebug() < <"The user clicked No.";                            
        break;                                          
        defaul:                                         
        break; }});Copy the code

Click Yes button and No button of the dialog box successively to achieve the effect:

File dialog box

File dialog box is also very common, for example, we often need to open an existing project in a program, this time will pop up a file dialog box. When we select the target file and click OK, the complete absolute path to the file is returned to us as a string.

To use the file dialog, you must first import header files.

If we want to get the path to an open file, we call the getOpenFileName method.

P. :

The first parameter, parent, specifies the parent component. Note that many Qt component constructors take the parent argument and provide a default value of 0; The second argument, caption, is the dialog’s title; The third parameter, dir, is the default directory to open when the dialog is displayed.”.” represents the program running directory, and “/” represents the root directory of the current drive letter (on Windows, Linux/is the root directory). It can also be platform-specific, such as “C:\”, etc. For example, if I want to open the Data folder in the program run directory as the default path, I should write it as “./Data/”. If I want to have a file selected by default, I can add the file name after the directory: “./Data/teaser.graph” the fourth parameter filter is the extension name filter of the dialog box. For example, we use “Image Files(.jpg.png)” to make it only display JPG or PNG Files. If you need to use multiple filters, use “;;”. Split, such as “JPEG Files(.jpg); PNG Files (. PNG) “; The fifth parameter, selectedFilter, is the default filter selected; The sixth parameter options, are some of the parameters setting dialog box, only show the folder, and so on, for example, it is the value of enum QFileDialog: : Option, each of these options can be combined in use | operation. What if I want to select multiple files? Qt provides the getOpenFileNames() function, which returns a QStringList. You can think of it as a List that only holds QStrings, the List in the STL.

[From: blog.csdn.net/qq_38400517…]

connect(pCreate,&QAction::triggered,[=](){         
   QFileDialog::getOpenFileName(this."open".".. /");    // Relative path is the parent directory of the current program path
}); 
Copy the code

Effect:

If we also want to specify a range of file types, we need to set the filter parameter. Different file names of the same type are separated by Spaces, and files of different types are separated by;; Space.

connect(pCreate,&QAction::triggered,[=](){
    QFileDialog::getOpenFileName(this."open".".. /"."source(*.cpp *.h);; image(*.jpg *.bmp);; all(*.*)");
});  
Copy the code

P.S: if you think the string is too long, you can use the Enter key to wrap it, and C++ will automatically add missing double quotes.

Effect:

P.S: If there is any error, welcome to correct ~