您好,登錄后才能下訂單哦!
這篇文章主要介紹了Qt怎么使用QDialog實現界面遮罩的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Qt怎么使用QDialog實現界面遮罩文章都會有所收獲,下面我們一起來看看吧。
先來看下效果:
根據需求功能,我們需要提供設置主窗口的接口,同樣的,并不是說所有的窗口都需要進行遮罩,那么我們也同樣需要知道哪些窗口是需要遮罩的,因此,還需要提供一個判斷的標準,在一個工程里面,每個UI文件的objectName是獨一份的,因此我們可以通過這些objectName來判斷哪些dialog需要遮罩。
該類是在需要被遮罩的dialog顯示出來的時候自動調用顯示,而不需要手動調用,因此需要檢測全局的事件循環。
以上,我們來看下該組件的頭文件定義:
#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
由上面的類定義也能夠看出來,這個組件還是比較簡單的,簡單到只有兩個接口和一個事件過濾函數,所以下面,我們來具體看下其中的實現。
首先是千篇一律的單例實現,該組件在整個工程中獨一份就好,多了可能就會出現你想不到的情況(多層覆蓋或者沖突了):
MaskWidget * MaskWidget::m_pSelf = Q_NULLPTR; MaskWidget * MaskWidget::instance() { if (m_pSelf == Q_NULLPTR) { m_pSelf = new MaskWidget; } return m_pSelf; }
在其構造中,我們需要設置一些window相關的屬性,并且將該窗口先隱藏起來,要不然程序一打開就會看到整個上面有一層灰蒙蒙的遮罩。其實最主要的是需要在其構造函數里面注冊事件過濾。
MaskWidget::MaskWidget(QWidget *parent) : QDialog(parent), ui(new Ui::MaskWidget) { ui->setupUi(this); hide(); setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowDoesNotAcceptFocus); qApp->installEventFilter(this); }
在主程序啟動之后,我們還要做兩件事,也就是我們前面說的兩個接口需要調用實現,一個是設置需要遮罩的主窗口,一個是需要設置彈出需要遮罩的窗口的名稱,先看下設置主窗口。
void MaskWidget::setMainWidget(QWidget *pWidget) { this->setFixedSize(QSize(pWidget->width(), pWidget->height())); this->setParent(pWidget); this->move(pWidget->x(), pWidget->y()); }
由上面可以看出,設置主窗口之后,我們將該組件的父類也設置為了主窗口,這樣就能保證該組件顯示出來的時候一定是以設置的主窗口為父節點進行顯示,并且能夠鋪滿整個主窗口。
顯示窗口的設置也是比較簡單的屬性的操作方式,如下:
void MaskWidget::setNames(const QStringList& names) { if(m_listName == names) { return; } m_listName = names; } QStringList MaskWidget::names() const { return names; }
在整個過程中,其實最主要的是事件過濾函數的實現,該函數基本包含了該組件的基本功能,下面我們看下該函數的實現。
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轉換為普通QWidget if (Q_NULLPTR == pWidget) { return QObject::eventFilter(obj, event); } pWidget->activateWindow(); pWidget->setFocus(Qt::ActiveWindowFocusReason); stackUnder(pWidget); //將該窗口設置放到彈窗的下面 if(Q_NULLPTR == m_pMainWidget) { return QObject::eventFilter(obj, event); } m_pMainWidget->stackUnder(this); //將主窗口設置放到該組件界面下方,就能夠有一個比較清晰的層次關系 //下面是實現將彈窗的位置移動到主程序的正中間,在這邊實現的目的是為了減少代碼量,畢竟寫代碼能偷的懶還是一定要偷的 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,并且在調用時使用QDialog::exec()函數實現模態。如果不實現模態的話,會出現一些意外,當然這些意外并不影響使用,只是交互上面會比較不友好。假設你的主程序不能移動,那么就會很不友好。
TestDialog dlg; if(QDialog::Accept == dlg.exec()) { }
關于“Qt怎么使用QDialog實現界面遮罩”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Qt怎么使用QDialog實現界面遮罩”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。