单击时在QWidget上绘制矩形叠加层

时间:2013-10-05 16:15:17

标签: qt qwidget

在我的项目中,我使用EventFilter作为QHBoxLayout中的小部件。

如果我点击一个小部件,我想在点击的小部件上绘制一个蓝色的透明覆盖。 有没有办法实现这个?

问候

2 个答案:

答案 0 :(得分:14)

这个答案出现在我的与叠加相关的一系列答案中:firstsecondthird

这样做的一种方法是:

  1. 拥有一个对鼠标事件透明的半透明叠加小部件。

  2. 在事件过滤器中,通过调整叠加层的几何图形以匹配目标窗口小部件的几何图形来跟踪对象的单击和调整大小。

  3. 下面的自包含示例在Qt 4和Qt 5下都能正常运行,并且可以满足您的需要。

    screenshot

    // https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-19199863
    #include <QtGui>
    #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    #include <QtWidgets>
    #endif
    
    class Overlay : public QWidget {
    public:
        explicit Overlay(QWidget *parent = nullptr) : QWidget(parent) {
            setAttribute(Qt::WA_NoSystemBackground);
            setAttribute(Qt::WA_TransparentForMouseEvents);
        }
    protected:
        void paintEvent(QPaintEvent *) override {
            QPainter(this).fillRect(rect(), {80, 80, 255, 128});
        }
    };
    
    class OverlayFactoryFilter : public QObject {
        QPointer<Overlay> m_overlay;
    public:
        explicit OverlayFactoryFilter(QObject *parent = nullptr) : QObject(parent) {}
    protected:
        bool eventFilter(QObject *obj, QEvent *ev) override {
            if (!obj->isWidgetType()) return false;
            auto w = static_cast<QWidget*>(obj);
            if (ev->type() == QEvent::MouseButtonPress) {
                if (!m_overlay) m_overlay = new Overlay;
                m_overlay->setParent(w);
                m_overlay->resize(w->size());
                m_overlay->show();
            }
            else if (ev->type() == QEvent::Resize) {
                if (m_overlay && m_overlay->parentWidget() == w)
                    m_overlay->resize(w->size());
            }
            return false;
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        OverlayFactoryFilter factory;
        QWidget window;
        QHBoxLayout layout(&window);
        for (auto text : { "Foo", "Bar", "Baz "}) {
            auto label = new QLabel{text};
            layout.addWidget(label);
            label->installEventFilter(&factory);
        }
        window.setMinimumSize(300, 250);
        window.show();
        return a.exec();
    }
    

答案 1 :(得分:1)

在重叠窗口小部件构造函数中:

    setWindowFlags(Qt::Widget | Qt::FramelessWindowHint | Qt::ToolTip | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_NoSystemBackground, true);
    setAttribute(Qt::WA_TranslucentBackground, true);

在拥有该小部件的窗口中:

overlay_ = new RtspOverlay(this);
overlay_->show();