current position:Home>QT use qdialog to realize interface mask (mask)

QT use qdialog to realize interface mask (mask)

2022-04-29 13:13:35slowlytalk

In the process of writing applications , Pop up is an unavoidable function , Showing , Suppose that the background color of the pop-up window is similar to that of the main window , Even at the same time , There will be a serious human-computer interaction and UI The problems shown , Finding the boundary of the pop-up window is a troublesome thing . But if we can add a background color to other parts of the main window when the pop-up window is displayed , This background color forms a relatively large color difference with the background color of the pop-up window , So can you easily find the boundary of the pop-up window . therefore , We implement a custom component , You can set the main window that needs to be masked at will , And it can follow the movement of the main window .

Let's look at the effect first :  Insert picture description here

  • Function according to requirements , We need to provide an interface for setting the main window , alike , Not all windows need to be masked , Then we also need to know which windows need to be masked , therefore , We also need to provide a judgment standard , In a project , Every UI Of documents objectName It's the only one , So we can use these objectName To judge what dialog Mask required .
  • This class is used when it needs to be masked dialog Automatically call the display when it is displayed , You don't need to call it manually , Therefore, it is necessary to detect the global event loop .

above , Let's take a look at the header file definition of this component :

#ifndef MASK_WIDGET_H
#define MASK_WIDGET_H

#include <QDialog>

namespace Ui {
    class MaskWidget;
}
class MaskWidget : public QDialog
{
    Q_OBJECT Q_PROPERTY(QStringList names READ names WRITE setNames DESIGNABLE true) public: static MaskWidget *instance();

    void setMainWidget(QWidget* pWidget);
    
    QStringList names() const;
 	void setNames(const QStringList& names);


protected:
    bool eventFilter(QObject *obj, QEvent *event);

private:
    explicit MaskWidget(QWidget *parent = Q_NULLPTR);
    ~MaskWidget();

private:
    Ui::MaskWidget* ui;
   
    QStringList m_listName{ QStringList() };

    QWidget* m_pMainWidget{ Q_NULLPTR };

    static MaskWidget* m_pSelf;
};

#endif // MASK_WIDGET_H
 Copy code 

It can also be seen from the above class definition , This component is relatively simple , It's as simple as two interfaces and an event filter function , So below , Let's look at the implementation .

The first is the same singleton implementation , This component is the only one in the whole project , If there are more, you may have unexpected situations ( Multiple layers of coverage or conflict ):

MaskWidget * MaskWidget::m_pSelf = Q_NULLPTR;

MaskWidget * MaskWidget::instance() {
	if (m_pSelf == Q_NULLPTR)
	{
		m_pSelf = new MaskWidget;
	}
	return m_pSelf;
}
 Copy code 

In its structure , We need to set up some window Related properties , And hide the window first , Otherwise, as soon as the program opens, you will see a gray mask on the whole . In fact, the most important thing is to register event filtering in its constructor .

MaskWidget::MaskWidget(QWidget *parent) : QDialog(parent), ui(new Ui::MaskWidget)
{
    ui->setupUi(this);
    hide();
    setWindowFlags(Qt::FramelessWindowHint | Qt::Tool |  Qt::WindowDoesNotAcceptFocus);
    qApp->installEventFilter(this);
}
 Copy code 

After the main program starts , We have two more things to do , That is, the two interfaces we mentioned earlier need to call the implementation , One is to set the main window that needs to be masked , One is to set the name of the pop-up window that needs to be masked , Take a look at the setting main window first .

void MaskWidget::setMainWidget(QWidget *pWidget) {
    this->setFixedSize(QSize(pWidget->width(), pWidget->height()));
    this->setParent(pWidget);
    this->move(pWidget->x(), pWidget->y());
}
 Copy code 

You can see that from the top , After setting the main window , We also set the parent class of the component as the main window , In this way, it can be ensured that the component must be displayed with the set main window as the parent node , And can cover the whole main window .

The setting of the display window is also a relatively simple operation mode of properties , as follows :

void MaskWidget::setNames(const QStringList& names) {
     if(m_listName == names)
     {
         return;
     }
     m_listName = names;
 }

 QStringList MaskWidget::names() const {
     return names;
 }
 Copy code 

In the whole process , In fact, the most important thing is the implementation of event filtering function , This function basically contains the basic functions of the component , Let's look at the implementation of this function .

bool MaskWidget::eventFilter(QObject *obj, QEvent *event) {
    if(event->type() == QEvent::Hide)
    {
        if(m_listName.contains(obj->objectName()))
        {
            hide();
        }
        return QObject::eventFilter(obj, event);
    }

    if (event->type() == QEvent::Show) 
    {
        if (!m_listName.contains(obj->objectName()))
        {
            return QObject::eventFilter(obj, event);
        }

        show();

        auto pWidget = dynamic_cast<QWidget*>(obj);     // take object Convert to normal QWidget
        if (Q_NULLPTR == pWidget)
        {
            return QObject::eventFilter(obj, event);
        }
        pWidget->activateWindow();
        pWidget->setFocus(Qt::ActiveWindowFocusReason);
        stackUnder(pWidget);    // Put the window settings under the pop-up window 

        if(Q_NULLPTR == m_pMainWidget)
        {
            return QObject::eventFilter(obj, event);
        }

        m_pMainWidget->stackUnder(this);    // Put the main window settings at the bottom of the component interface , There can be a clear hierarchical relationship 

        // The following is to move the position of the pop-up window to the middle of the main program , The purpose of this implementation is to reduce the amount of code , After all, the laziness that can be stolen by writing code must be stolen 
        QRect screenGeometry = m_pMainWidget->geometry();
        int x = screenGeometry.x() + (screenGeometry.width() - pWidget->width()) / 2;
        int y = screenGeometry.y() + (screenGeometry.height() - pWidget->height()) / 2;
        pWidget->move(x, y);
    } 

    return QObject::eventFilter(obj, event);
}
 Copy code 

above , All the functions of this component are introduced .

In the process of using , Include files directly to use , It should be noted that , Pop up dialog The base class of the window must QDialog, And use... When calling QDialog::exec() Function realization mode . If you don't implement modes , There will be some accidents , Of course, these accidents do not affect the use of , It's just that the interaction will be unfriendly . Suppose your main program can't move , Then it will be very unfriendly .

TestDialog dlg;
if(QDialog::Accept == dlg.exec())
{

}
 Copy code 

Test code link :gitee.com/Gqian_com/c…

copyright notice
author[slowlytalk],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/04/202204291313293070.html

Random recommended