一、效果展示
最近做了一個提示框消失的功能,覺着挺有意思,以前一直以為Qt子窗口不能做淡出效果,其實Qt的淡出功能已經幫我們封裝好了,我們僅僅只需要幾行代碼就可以做出酷炫的窗口關閉效果,寫此篇文章的時候,我特意瀏覽了下之前寫的兩篇文章(QPainterPath 不規則提示框,QPainterPath 不規則提示框(二)),現在回想起來那會兒確實知之甚少,關於頂層窗口不能做圓角,其實幫助文檔里已經說的很明確,解決辦法有多種,一種是重寫paintEvent函數,另一種是把widget包裝一層,本篇文章就用的是后一種方式,如圖1所示窗口關閉動畫,實例程序中做了淡出、飛出、縮小等關閉窗口動畫,除此之外還包含了陰影、背景着色、濾鏡等特效。

圖1 窗口特效
二、功能
如圖1窗口特效所示,實例中總共包含了4個groupbox,這4個groupbox是分別用來展示不同特效,下面分別講述4個groupbox
- 背景色:主要針對窗口背景色進行了定制,就像groupbox中按鈕文字那樣,是紅色和綠色的背景提示框,其中紅色提示框使用了最小化關閉效果,綠色提示框使用了淡出特效
- 飛出:這4個按鈕彈出的對話框都使用了飛出特效,4個按鈕分別展示了4種飛出的方式(左、上、右、下)
- 自定義:支持自定義提示框別景色、提示框展示時長、消失動畫時長和消失模式
- shortcut:主要是針對業務進行的功能定制,warning提示框體的圖標是進行單獨處理的,是一個嘆號圖標
三、代碼實現
在講解代碼之前,先來認識幾個概念
- QPropertyAnimation:屬性動畫,可以參考qt 窗口動畫
- QGraphicsOpacityEffect:窗口透明度設置類,繼承自QGraphicsEffect
- QGraphicsDropShadowEffect:窗口陰影,繼承自QGraphicsEffect
- QGraphicsBlurEffect:濾鏡,繼承自QGraphicsEffect
- QGraphicsColorizeEffect:着色,繼承自QGraphicsEffect
1、移出動畫,使用屬性動畫QPropertyAnimation類進行,propertyname的參數是窗口的屬性,詳情參見Q_PROPERTY屬性 。targetObject對象設置為this內部單獨封裝的widget,這樣做的目的使得該提示框不需要依賴其他窗口遮擋即可做出飛出效果
1 void GMPOperateTip::MoveOut() 2 { 3 m_pAnimation->setTargetObject(m_pMoveWidget); 4 m_pAnimation->setPropertyName("pos"); 5 6 m_pAnimation->setStartValue(QPoint()); 7 switch (m_eDirection) 8 { 9 case D_LEFT: 10 m_pAnimation->setEndValue(QPoint(-width(), 0)); 11 break; 12 case D_TOP: 13 m_pAnimation->setEndValue(QPoint(0, -height())); 14 break; 15 case D_RIGHT: 16 m_pAnimation->setEndValue(QPoint(width(), 0)); 17 break; 18 case D_BOTTOM: 19 m_pAnimation->setEndValue(QPoint(0, height())); 20 break; 21 default: 22 ; 23 } 24 }
2、淡出
1 m_pOpacity = new QGraphicsOpacityEffect(this); 2 m_pOpacity->setOpacity(1); 3 4 setGraphicsEffect(m_pOpacity); 5 6 m_pAnimation->setTargetObject(m_pOpacity); 7 m_pAnimation->setPropertyName("opacity"); 8 9 m_pAnimation->setStartValue(1); 10 m_pAnimation->setEndValue(0);
3、最小化
1 m_pAnimation->setPropertyName("geometry"); 2 3 QRect startRect = rect(); 4 startRect.moveTo(pos()); 5 QRect stopRect = QRect(startRect.center(), QSize(0, 0)); 6 7 m_pAnimation->setStartValue(startRect); 8 m_pAnimation->setEndValue(stopRect);
4、動畫啟動機制
使用定時器控制動畫,當指定時間后啟動動畫,並且在動畫完成后關閉窗口
1 void InitializeConnect() 2 { 3 m_pAnimation = new QPropertyAnimation(this); 4 m_pAnimation->setTargetObject(this); 5 6 connect(m_pAnimation, &QPropertyAnimation::finished, this, &GMPOperateTip::close); 7 8 connect(&m_StayTimer, &QTimer::timeout, this, [this]{ 9 m_pAnimation->setDuration(m_DurationTime); 10 switch (m_eMode) 11 { 12 case AM_FADEOUT: 13 FadeOut_p(); 14 break; 15 case AM_FLYOUT: 16 MoveOut(); 17 break; 18 case AM_ZOOMIN: 19 ZoomIn(); 20 break; 21 default: 22 ; 23 } 24 25 m_pAnimation->start(); 26 }); 27 }
窗口顯示時啟動定時器,並且將窗口隨機移動到屏幕一個位置
1 bool event(QEvent * e) 2 { 3 if (e->type() == QEvent::Show) 4 { 5 //QPoint pos = parentWidget()->rect().center() - this->rect().center(); 6 int wrand = qrand() % (parentWidget()->rect().width() - this->rect().width()); 7 int hrand = qrand() % (parentWidget()->rect().height() - this->rect().width()); 8 move(QPoint(wrand, hrand)); 9 10 m_StayTimer.start(m_iStayDuration); 11 } 12 13 return __super::event(e); 14 }
5、陰影
1 void setShadowEnable(bool enable) 2 { 3 if (!m_pShadow) 4 { 5 m_pShadow = new QGraphicsDropShadowEffect(this); 6 m_pShadow->setColor(QColor(0, 0, 0, 85)); 7 m_pShadow->setBlurRadius(10); 8 m_pShadow->setOffset(4, 4); 9 } 10 11 setGraphicsEffect(enable ? m_pShadow : nullptr); 12 }
6、着色
注釋中的代碼也可以進行着色,但是窗體的一些特殊樣式不能完成,因此使用stylesheet來完成背景色修改
1 static const QString c_szStyleSheet = "QWidget{background-color:%1;\ 2 border:1px solid %2;border-top:0;border-bottom-left-radius:3px;\ 3 border-bottom-right-radius:3px;background-image: url();}";
1 void GMPOperateTip::setBackgroundColor(const QColor & color) 2 { 3 //if (!m_pColorize) 4 //{ 5 // m_pColorize = new QGraphicsColorizeEffect(this); 6 // m_pColorize->setStrength(1); 7 // 8 // setGraphicsEffect(m_pColorize); 9 //} 10 //m_pColorize->setColor(color); 11 12 QColor border = color; 13 border.setAlpha(255 * 0.1); 14 QString borderRgba = QString("rgba(%1,%2,%3,%4)").arg(border.red()).arg(border.green()).arg(border.blue()).arg(border.alpha()); 15 setStyleSheet(c_szStyleSheet.arg(color.name()).arg(borderRgba)); 16 }
7、快捷調用接口,該接口都是類的靜態方法可以直接調用
View Code
8、測試,由於測試代碼較多,我只貼出2個
1 void tip::on_pushButton_success_clicked()
2 { 3 GMPOperateTip::Success(this, QStringLiteral("測a試º?,ê?測a試º?"), 1000, 1000); 4 } 5 6 void tip::on_pushButton_warning_clicked() 7 { 8 GMPOperateTip::Waring(this, QStringLiteral("測a試º?,ê?測a試º?"), 1000, 1000); 9 }
四、demo程序
![]() |
![]() |
很重要--轉載聲明
- 本站文章無特別說明,皆為原創,版權所有,轉載時請用鏈接的方式,給出原文出處。同時寫上原作者:朝十晚八 or Twowords
- 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目的。


