" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt 使用QDialog實(shí)現(xiàn)界面遮罩的示例(蒙版)

 更新時(shí)間:2022年04月29日 11:43:25   作者:slowlytalk  
界面遮罩在很多時(shí)候都可以用到,例如彈窗,本文主要介紹了Qt 使用QDialog實(shí)現(xiàn)界面遮罩的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

寫應(yīng)用程序的過程中,彈窗是個(gè)避免不了的功能,顯示中,假設(shè)彈窗背景色和主窗口背景色相差不多,甚至是一樣的時(shí)候,就會存在一個(gè)比較嚴(yán)重的人機(jī)交互和UI顯示的問題,找到彈窗的邊界是比較麻煩的一件事。但是如果我們能在彈窗顯示的時(shí)候被主窗口其他的部位增加一個(gè)背景色,這個(gè)背景色與彈窗的背景色形成比較大的色差,那么是不是就能夠很容易的找到彈窗的邊界。因此,我們實(shí)現(xiàn)一個(gè)自定義組件,可隨便設(shè)置需要遮罩的主窗口,并且能夠讓其跟隨主窗口的移動而移動。

先來看下效果:

  • 根據(jù)需求功能,我們需要提供設(shè)置主窗口的接口,同樣的,并不是說所有的窗口都需要進(jìn)行遮罩,那么我們也同樣需要知道哪些窗口是需要遮罩的,因此,還需要提供一個(gè)判斷的標(biāo)準(zhǔn),在一個(gè)工程里面,每個(gè)UI文件的objectName是獨(dú)一份的,因此我們可以通過這些objectName來判斷哪些dialog需要遮罩。
  • 該類是在需要被遮罩的dialog顯示出來的時(shí)候自動調(diào)用顯示,而不需要手動調(diào)用,因此需要檢測全局的事件循環(huán)。

以上,我們來看下該組件的頭文件定義:

#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

由上面的類定義也能夠看出來,這個(gè)組件還是比較簡單的,簡單到只有兩個(gè)接口和一個(gè)事件過濾函數(shù),所以下面,我們來具體看下其中的實(shí)現(xiàn)。

首先是千篇一律的單例實(shí)現(xiàn),該組件在整個(gè)工程中獨(dú)一份就好,多了可能就會出現(xiàn)你想不到的情況(多層覆蓋或者沖突了):

MaskWidget * MaskWidget::m_pSelf = Q_NULLPTR;

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

在其構(gòu)造中,我們需要設(shè)置一些window相關(guān)的屬性,并且將該窗口先隱藏起來,要不然程序一打開就會看到整個(gè)上面有一層灰蒙蒙的遮罩。其實(shí)最主要的是需要在其構(gòu)造函數(shù)里面注冊事件過濾。

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

在主程序啟動之后,我們還要做兩件事,也就是我們前面說的兩個(gè)接口需要調(diào)用實(shí)現(xiàn),一個(gè)是設(shè)置需要遮罩的主窗口,一個(gè)是需要設(shè)置彈出需要遮罩的窗口的名稱,先看下設(shè)置主窗口。

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

由上面可以看出,設(shè)置主窗口之后,我們將該組件的父類也設(shè)置為了主窗口,這樣就能保證該組件顯示出來的時(shí)候一定是以設(shè)置的主窗口為父節(jié)點(diǎn)進(jìn)行顯示,并且能夠鋪滿整個(gè)主窗口。

顯示窗口的設(shè)置也是比較簡單的屬性的操作方式,如下:

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

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

在整個(gè)過程中,其實(shí)最主要的是事件過濾函數(shù)的實(shí)現(xiàn),該函數(shù)基本包含了該組件的基本功能,下面我們看下該函數(shù)的實(shí)現(xiàn)。

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);     //將object轉(zhuǎn)換為普通QWidget
        if (Q_NULLPTR == pWidget)
        {
            return QObject::eventFilter(obj, event);
        }
        pWidget->activateWindow();
        pWidget->setFocus(Qt::ActiveWindowFocusReason);
        stackUnder(pWidget);    //將該窗口設(shè)置放到彈窗的下面

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

        m_pMainWidget->stackUnder(this);    //將主窗口設(shè)置放到該組件界面下方,就能夠有一個(gè)比較清晰的層次關(guān)系

        //下面是實(shí)現(xiàn)將彈窗的位置移動到主程序的正中間,在這邊實(shí)現(xiàn)的目的是為了減少代碼量,畢竟寫代碼能偷的懶還是一定要偷的
        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);
}

以上,該組件的全部功能介紹完了。

使用的過程中了,直接包含文件就能夠使用,需要注意的是,彈出的dialog窗口的基類必須QDialog,并且在調(diào)用時(shí)使用QDialog::exec()函數(shù)實(shí)現(xiàn)模態(tài)。如果不實(shí)現(xiàn)模態(tài)的話,會出現(xiàn)一些意外,當(dāng)然這些意外并不影響使用,只是交互上面會比較不友好。假設(shè)你的主程序不能移動,那么就會很不友好。

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

}

測試代碼鏈接:https://gitee.com/Gqian_com/customcomponent/tree/master/maskwidget

到此這篇關(guān)于Qt 使用QDialog實(shí)現(xiàn)界面遮罩的示例(蒙版)的文章就介紹到這了,更多相關(guān)Qt  QDialog界面遮罩內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C/C++ 監(jiān)控磁盤與目錄操作的示例

    C/C++ 監(jiān)控磁盤與目錄操作的示例

    這篇文章主要介紹了C/C++ 監(jiān)控磁盤與目錄操作的示例,幫助大家更好的理解和學(xué)習(xí)C/C++編程,感興趣的朋友可以了解下
    2020-10-10
  • C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等

    C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等

    這篇文章主要為大家介紹了C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • C++實(shí)現(xiàn)LeetCode(50.求x的n次方)

    C++實(shí)現(xiàn)LeetCode(50.求x的n次方)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(50.求x的n次方),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 使用Qt實(shí)現(xiàn)旋轉(zhuǎn)動畫效果

    使用Qt實(shí)現(xiàn)旋轉(zhuǎn)動畫效果

    這篇文章主要為大家詳細(xì)介紹了如何使用Qt實(shí)現(xiàn)旋轉(zhuǎn)動畫效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • C++ 逗號運(yùn)算符的具體使用

    C++ 逗號運(yùn)算符的具體使用

    本文主要介紹了C++ 逗號運(yùn)算符的具體使用,使用逗號運(yùn)算符是為了把幾個(gè)表達(dá)式放在一起,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • 一文詳解C語言中的switch語句和while循環(huán)

    一文詳解C語言中的switch語句和while循環(huán)

    這篇文章主要給大家詳細(xì)介紹了C語言中的switch語句和while循環(huán),文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • 二叉樹先根(先序)遍歷的改進(jìn)

    二叉樹先根(先序)遍歷的改進(jìn)

    這篇文章主要介紹了二叉樹先根(先序)遍歷的改進(jìn),有需要的朋友可以參考一下
    2014-01-01
  • C語言編程數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列

    C語言編程數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列

    本篇文章是C語言編程篇,主要為大家介紹C語言編程中的數(shù)據(jù)結(jié)構(gòu),詳細(xì)的講解了數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09
  • C++ pair的基本用法總結(jié)整理

    C++ pair的基本用法總結(jié)整理

    這篇文章主要介紹了C++ pair的基本用法總結(jié)整理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • vscode終端中打不開conda虛擬包管理的解決

    vscode終端中打不開conda虛擬包管理的解決

    本文主要介紹了vscode終端中打不開conda虛擬包管理的解決,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09

最新評論

滦平县| 驻马店市| 元阳县| 迭部县| 文登市| 集贤县| 达拉特旗| 常州市| 罗定市| 庆城县| 军事| 临泽县| 军事| 封开县| 仁寿县| 定远县| 巩义市| 孝感市| 克什克腾旗| 青阳县| 新昌县| 射阳县| 云龙县| 辽阳县| 萨迦县| 抚顺县| 十堰市| 庆阳市| 靖宇县| 永州市| 江油市| 元朗区| 潢川县| 清河县| 庆元县| 陆川县| 姚安县| 元阳县| 秦安县| 万州区| 容城县|