Calling the hide function for a widget only hides the visual representation, not the widget itself
-
All of my widgets inherit from QWidget. When a widget that uses winId() to display video calls hide(), the video display is hidden, but the widget's background remains visible. This indicates that the widget isn't hidden immediately. For another widget that also uses winId() (to test if it's due to the native window), but draws images in the PaintEvent, calling hide() results in no response, which is the expected behavior.
Is there a way to make the hide action for the video widget behave the same way as the image widget's hide action? -
Please provide some code on how you show your widget - a minimal, compilable example.
-
#pragma once #include <QWidget> #include <mpv/client.h> class InheritWidget : public QWidget { Q_OBJECT public: InheritWidget(QWidget* parent); void Init(); private: mpv_handle* mpv; };
#include "InheritWidget.h" InheritWidget::InheritWidget(QWidget* parent) :QWidget(parent) { } void InheritWidget::Init() { mpv = mpv_create(); if (!mpv) { qDebug() << "could not create mpv context"; throw std::runtime_error("could not create mpv context"); } int64_t wid = this->winId(); mpv_set_property(mpv, "wid", MPV_FORMAT_INT64, &wid); qDebug() << "wid is " << wid; mpv_set_property_string(mpv, "hwdec", "auto"); mpv_set_property_string(mpv, "loop-file", "inf"); if (mpv_initialize(mpv) < 0) { qDebug() << "could not initialize mpv context"; throw std::runtime_error("could not initialize mpv context"); } const char* args[] = { "loadfile", "4k_60.mp4", NULL }; mpv_command_async(mpv, 0, args); }
#pragma once #include <QWidget> #include "InheritWidget.h" class MyWidget: public QWidget { public: MyWidget(QWidget *parent); void SetSubWidget(); void hide(); private: InheritWidget* videoWidget; };
#include "Mywidget.h" MyWidget::MyWidget(QWidget* parent) : QWidget(parent) { this->setGeometry(0,0, 1920, 1080); this->setWindowFlags(Qt::FramelessWindowHint); QPalette palette; palette.setColor(QPalette::Window, Qt::GlobalColor::white); this->setAutoFillBackground(true); this->setPalette(palette); } void MyWidget::SetSubWidget() { InheritWidget*subWidget = new InheritWidget(this); subWidget->setGeometry(0, 0, 1000, 1000); QPalette palette; palette.setColor(QPalette::Window, Qt::GlobalColor::black); subWidget->setAutoFillBackground(true); subWidget->winId(); subWidget->setPalette(palette); subWidget->show(); InheritWidget* ssubWidget = new InheritWidget(subWidget); ssubWidget->setGeometry(0, 0, 960, 540); QPalette palette1; palette1.setColor(QPalette::Window, Qt::GlobalColor::red); ssubWidget->setAutoFillBackground(true); ssubWidget->winId(); ssubWidget->setPalette(palette1); ssubWidget->Init(); ssubWidget->show(); videoWidget = ssubWidget; } void MyWidget::hide() { videoWidget->hide(); }
#include <QWidget> #include "Mywidget.h" #include <QApplication> #include <QTimer> int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setAttribute(Qt::AA_NativeWindows); MyWidget *mywidget = new MyWidget(nullptr); mywidget->show(); QTimer::singleShot(2000, mywidget, [&]() { mywidget->SetSubWidget(); }); QTimer::singleShot(5000, mywidget, [&]() { mywidget->hide(); }); return app.exec();; }
Do you need videofile and libmpv?
-
@Quiccz I do not see the behaviour you describe with respect to the background of the "ssubWidget" on Ubuntu/KDE/Qt 6.6. The widget playing video is hidden and the MPV widget black background is all I see (the video is still playing and audio is there).
It is, however, unclear what you are trying to achieve with the somewhat circuitous setup of nested widgets without layouts.
-
@ChrisW67 Did you use breakpoint in mpvwidget->hide(); i mean after call hide(), mpvwidget show backgroud color immediately
I'm working on a player that receives a JSON playlist, and it has no border and the window is non-resizable. Therefore, I'm using a layered approach with multiple widgets to achieve this.
like
{ "program1": [ { "x" : 0, "y" : 0, "width" : 100, "height" : 100, "file" : "1.mp4" }, { "x" : 100, "y" : 100, "width" : 100, "height" : 100, "file" : "2.mp4" } ], "program2": [ { "x" : 0, "y" : 0, "width" : 100, "height" : 100, "file" : "3.jpg" }, { "x" : 100, "y" : 100, "width" : 100, "height" : 100, "file" : "4.jpg" } ] }
-
@Quiccz said in Calling the hide function for a widget only hides the visual representation, not the widget itself:
Did you use breakpoint in mpvwidget->hide(); i mean after call hide(), mpvwidget show backgroud color immediately
Why would I do that? You certainly didn't say you were deliberately halting program execution. Halting execution after calling hide() but before the Qt event loop is reached more-or-less guarantees that part or all of the rendering is incomplete.
-
@ChrisW67 Because when switching videos in my program, I noticed a brief moment where a red background was visible. So, I added breakpoints to debug. I discovered that when I used video hide(), the video frame disappeared immediately instead of staying on the last frame until the next event loop. I was just curious about why this was happening. Of course, I eventually resolved the issue by changing the order of hide() and show()
-
@ChrisW67 If you overlay a transparent widget on top of the MPVWidget, you will notice that you see the background color of the MVPWidget instead of the video. I believe this is for the same reason as the immediate display of the video's background when using hide().
-