在我的项目中,我使用 a EventFilter
for 小部件,它们位于QHBoxLayout
.
如果我单击一个小部件,我想在单击的小部件上绘制一个蓝色的透明覆盖层。有没有办法实现这个?
问候
这个答案在我的一系列与叠加相关的答案中:first , second , third。
一种方法是:
有一个对鼠标事件也是透明的半透明覆盖小部件。
在事件过滤器中,通过调整叠加层的几何形状以匹配目标小部件的几何形状来跟踪对象的点击和调整大小。
下面的独立示例在 Qt 4 和 Qt 5 下都可以使用,并且可以满足您的需求。
// 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();
}
在覆盖小部件构造函数中:
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();