我有一个基于
QWidget
的覆盖小部件,它应该绘制一些文本并发生在我的应用程序的中央小部件上。问题是我无法将覆盖小部件的背景设置为透明。我已经尝试过的:
setPalette(Qt::transparent);
setAttribute( Qt::WA_TranslucentBackground, true );
setAttribute( Qt::WA_OpaquePaintEvent, true );
setAutoFillBackground(false);
setStyleSheet("QWidget{background-color: transparent;}");
setAttribute(Qt::WA_NoSystemBackground);
我对显示覆盖小部件的最佳猜测是将小部件转换为窗口,将其大小调整为内容并手动将它们移动到所需的位置。
MainWindow 示例,在视频小部件的中心显示覆盖小部件:
Mwindow::Mwindow()
{
widget = new Widget(this);
}
void Mwindow::widgetSizeMove()
{
if (widget->width() <= videoWidget->width() && widget->height() <= videoWidget->height())
{
widget->setWindowOpacity(1); // Show the widget
QPoint p = videoWidget->mapToGlobal(videoWidget->pos());
int x = p.x() + (videoWidget->width() - widget->width()) / 2;
int y = p.y() + (videoWidget->height() - widget->height()) / 2;
widget->move(x, y);
widget->raise();
}
else
{
widget->setWindowOpacity(0); // Hide the widget
}
}
bool Mwindow::event(QEvent *event)
{
switch (event->type())
{
case QEvent::Show:
widget->show();
QTimer::singleShot(50, this, SLOT(widgetSizeMove()));
//Wait until the Main Window be shown
break;
case QEvent::WindowActivate:
case QEvent::Resize:
case QEvent::Move:
widgetSizeMove();
break;
default:
break;
}
return QMainWindow::event(event);
}
小部件示例:
Widget::Widget(QWidget *parent) : QWidget(parent)
{
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_TransparentForMouseEvents);
}
void Widget::paintEvent(QPaintEvent*)
{
QPainter p(this);
QString text = "Some foo goes here";
QFontMetrics metrics(p.font());
resize(metrics.size(0, text));
p.drawText(rect(), Qt::AlignCenter, text);
}
使用 LibVLC 显示视频的示例:
在 Linux 上适用于:
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
最佳解决方案由Gökmen Göksel在本文章
的评论之一中提供setStyleSheet("background-color: rgba(0,0,0,0)");
这就是创建透明 QWidget 的方法。重要的是,如果您删除 Qt::FramelessWindowHint 那么透明度将不起作用。因此,如果您也想要标题栏,那么您需要创建一个自定义标题栏,没有解决方法。或者您可以使用 QML,它支持带有标准标题栏的透明度。
#include <QApplication>
#include <QLabel>
#include <QPainter>
class PaintEventFilter : public QObject {
protected:
bool eventFilter(QObject* obj, QEvent* event) override {
if (event->type() == QEvent::Paint) {
QWidget* widget = qobject_cast<QWidget*>(obj);
if (widget) {
QPainter painter(widget);
painter.setBrush(QBrush(QColor(0, 0, 255, 128)));
painter.drawRect(50, 100, 200, 100);
painter.setPen(Qt::white);
painter.drawText(widget->rect(), Qt::AlignCenter, "Transparent Window Test");
}
return true;
}
return QObject::eventFilter(obj, event);
}
};
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QWidget* wid = new QWidget();
wid->setWindowTitle("test");
wid->setGeometry({ 0,0,300,300 });
wid->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); // If you remove Qt::FramelessWindowHint, the transparency will not work!
wid->setAttribute(Qt::WA_TranslucentBackground);
QLabel* label = new QLabel("This is a transparent window", wid);
label->setStyleSheet("QLabel { color : white; font-size: 16px; }");
label->setGeometry(50, 50, 200, 50);
// Install the event filter
PaintEventFilter* filter = new PaintEventFilter();
wid->installEventFilter(filter);
wid->show();
return app.exec();
}