I want to add some controls and information on top of a fullscreen QVideoWidget
. So I create a QMainWindow
ui and then promote the central widget to QVideoWidget
as:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VideoScreen</class>
<widget class="QMainWindow" name="VideoScreen">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QVideoWidget" name="videoScreen">
<property name="styleSheet">
<string notr="true"/>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QVideoWidget</class>
<extends>QWidget</extends>
<header>QVideoWidget</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControlBoard</class>
<widget class="QWidget" name="ControlBoard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1044</width>
<height>520</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QLabel" name="title">
<property name="geometry">
<rect>
<x>210</x>
<y>90</y>
<width>59</width>
<height>17</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">
</string>
</property>
<property name="text">
<string>Title</string>
</property>
</widget>
<widget class="QPushButton" name="play">
<property name="geometry">
<rect>
<x>320</x>
<y>120</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>play</string>
</property>
</widget>
<widget class="QPushButton" name="stop">
<property name="geometry">
<rect>
<x>210</x>
<y>120</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>stop</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Then in videoscreen.cpp
, I also add the ControlBoard
as sibling of QVideoWidget
:
VideoScreen::VideoScreen(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::VideoScreen), player(new QMediaPlayer)
{
ui->setupUi(this);
player->setVideoOutput(ui->videoScreen);
ui->videoScreen->lower();
ControlBoard *cb = new ControlBoard(this);
}
When I play a video, the result:
How to make the ControlBoard
be transparent so that we can see the video behind?
I tried some code in ControlBoard
constructor:
// setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
// setAttribute(Qt::WA_NoSystemBackground);
// setAttribute(Qt::WA_TranslucentBackground);
// setAttribute(Qt::WA_PaintOnScreen);
// setAttribute(Qt::WA_TransparentForMouseEvents);
// setAutoFillBackground(false);
But this just show the parent's background, not the sibling video. Does Qt5 support this? Thanks!
UPDATE:
I also tried on some other like this (base on):
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 LoadingOverlay : public OverlayWidget
{
public:
LoadingOverlay(QWidget * parent = {}) : OverlayWidget{parent} {
setAttribute(Qt::WA_TranslucentBackground);
}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p(this);
// p.fillRect(rect(), {10, 10, 10, 100});
p.setPen({200, 200, 255});
p.setFont({"arial,helvetica", 48});
p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignVCenter);
}
};
int main(int argc, char * argv[])
{
QApplication a(argc, argv);
QMainWindow window;
QVideoWidget central(&window);
central.setMinimumSize(600, 700);
window.setCentralWidget(¢ral);
QMediaPlayer player;
player.setMedia(QUrl::fromLocalFile("dolbycanyon.mov"));
player.setVideoOutput(¢ral);
LoadingOverlay overlay(&window);
overlay.resize(400, 300);
overlay.setWindowOpacity(.4);
overlay.setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
overlay.setAttribute(Qt::WA_PaintOnScreen);
overlay.setAutoFillBackground(false);
// QTimer::singleShot(5000, &overlay, SLOT(hide()));
// QTimer::singleShot(7000, &player, SLOT(play()));
player.play();
window.show();
return a.exec();
}
Demo of transparent background overlay on the video: