2013-10-15 119 views

回答

8

這個答案是在我的覆蓋系列相關答案:first,second,third

如果您希望在所有平臺上都能正常工作,需要注意。您無法將效果直接應用到頂層窗口。層次結構需要看如下:

ContainerWidget 
    | 
    +----------+ 
    |   | 
**Target** Overlay 

您適用於Target插件的效果(比方說,一個QMainWindow)。 ContainerWidget是幫助孩子佔據小部件完整大小的輔助類。這消除了對明確的零邊界佈局的需要。

下面的工作,即使在Mac上。它不會,你有沒有放棄ContainerWidget。不幸的是,這僅適用於Qt 5。對QT 4,你的 「跨平臺」 支持的Mac排除它:(使用Qt的任一4(4.8.5)或Qt的5

screenshot

// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-blur-19383427 
#include <QtGui> 
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) 
#include <QtWidgets> 
#endif 

class OverlayWidget : public QWidget 
{ 
    void newParent() { 
     if (!parent()) return; 
     parent()->installEventFilter(this); 
     raise(); 
    } 
public: 
    explicit OverlayWidget(QWidget * parent = {}) : QWidget{parent} { 
     setAttribute(Qt::WA_NoSystemBackground); 
     setAttribute(Qt::WA_TransparentForMouseEvents); 
     newParent(); 
    } 
protected: 
    //! Catches resize and child events from the parent widget 
    bool eventFilter(QObject * obj, QEvent * ev) override { 
     if (obj == parent()) { 
     if (ev->type() == QEvent::Resize) 
      resize(static_cast<QResizeEvent*>(ev)->size()); 
     else if (ev->type() == QEvent::ChildAdded) 
      raise(); 
     } 
     return QWidget::eventFilter(obj, ev); 
    } 
    //! Tracks parent widget changes 
    bool event(QEvent* ev) override { 
     if (ev->type() == QEvent::ParentAboutToChange) { 
     if (parent()) parent()->removeEventFilter(this); 
     } 
     else if (ev->type() == QEvent::ParentChange) { 
     newParent(); 
     } 
     return QWidget::event(ev); 
    } 
}; 

class ContainerWidget : public QWidget 
{ 
public: 
    explicit ContainerWidget(QWidget * parent = {}) : QWidget{parent} {} 
    void setSize(QObject * obj) { 
     if (obj->isWidgetType()) static_cast<QWidget*>(obj)->setGeometry(rect()); 
    } 
protected: 
    //! Resizes children to fill the extent of this widget 
    bool event(QEvent * ev) override { 
     if (ev->type() == QEvent::ChildAdded) { 
     setSize(static_cast<QChildEvent*>(ev)->child()); 
     } 
     return QWidget::event(ev); 
    } 
    //! Keeps the children appropriately sized 
    void resizeEvent(QResizeEvent *) override { 
     for(auto obj : children()) setSize(obj); 
    } 
}; 

class LoadingOverlay : public OverlayWidget 
{ 
public: 
    LoadingOverlay(QWidget * parent = {}) : OverlayWidget{parent} { 
     setAttribute(Qt::WA_TranslucentBackground); 
    } 
protected: 
    void paintEvent(QPaintEvent *) override { 
     QPainter p{this}; 
     p.fillRect(rect(), {100, 100, 100, 128}); 
     p.setPen({200, 200, 255}); 
     p.setFont({"arial,helvetica", 48}); 
     p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignTop); 
    } 
}; 

#if QT_VERSION < QT_VERSION_CHECK(5,0,0) 
template <typename F> void singleShot(int period, F && fun) { 
    struct Helper : public QObject { 
     F fun; 
     QBasicTimer timer; 
     void timerEvent(QTimerEvent * event) override { 
     if (event->timerId() != timer.timerId()) return; 
     fun(); 
     deleteLater(); 
     } 
     Helper(int period, F && fun) : fun(std::forward<F>(fun)) { 
     timer.start(period, this); 
     } 
    }; 
    new Helper(period, std::forward<F>(fun)); 
} 
#else 
template <typename... Args> 
auto singleShot(Args&&... args) -> decltype(QTimer::singleShot(std::forward<Args>(args)...)) { 
    return QTimer::singleShot(std::forward<Args>(args)...); 
} 
#endif 

int main(int argc, char *argv[]) 
{ 
    QApplication a{argc, argv}; 
    ContainerWidget base; 
    QLabel label("Dewey, Cheatem and Howe, LLC.", &base); 
    label.setFont({"times,times new roman", 32}); 
    label.setAlignment(Qt::AlignCenter); 
    label.setGraphicsEffect(new QGraphicsBlurEffect); 
    LoadingOverlay overlay(&base); 
    base.show(); 
    singleShot(2000, [&]{ 
     overlay.hide(); 
     label.setGraphicsEffect({}); 
    }); 
    return a.exec(); 
} 
工程確定在Windows
0

如果您想對圖像應用模糊效果,可以參考this文章。創建模糊圖像後,您可以在QWidget::paintEvent()函數中繪製它。