Why is the display of a top-level transparent window slower?
-
I want to display multiple images that switch in a slideshow manner. If I display all the images within a single window, the switching is smooth. However, if each image is displayed in a separate top-level borderless window, there is a flickering effect during the switching process. This phenomenon only occurs when the images are initially displayed.
Here is my code:
#include <QPixmap> #include <QWidget> #include <QLabel> #include <QVector> #include <QTimer> class PicWidget : public QWidget { public: PicWidget(QWidget* parent = nullptr); void Load(QString file_path); void Play(); void Stop(); private: QLabel* m_label; QPixmap* m_pixmap; QWidget* m_widget; }; class PicWidgetManager : public QWidget { Q_OBJECT public: PicWidgetManager(QWidget* parent = nullptr); void Init(); public slots: void Start(); private: int m_index = 0; QVector<PicWidget*> m_pics; };
#include "PicWidget.h" #include <QFileInfo> #include <QImageReader> PicWidget::PicWidget(QWidget* parent) //: QWidget(parent) : QWidget(nullptr) { m_widget = new QWidget(nullptr); m_widget->setGeometry(0, 0, 1920, 1080); m_widget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); m_widget->setAttribute(Qt::WA_TranslucentBackground, true); m_widget->hide(); this->setParent(m_widget); this->hide(); } void PicWidget::Load(QString file_path) { QFileInfo file_info(file_path); m_label = new QLabel(this); m_label->hide(); m_pixmap = new QPixmap(file_info.absoluteFilePath()); m_label->setPixmap(*m_pixmap); } void PicWidget::Play() { m_label->show(); this->show(); m_widget->show(); } void PicWidget::Stop() { m_widget->hide(); this->hide(); m_label->hide(); m_label->deleteLater(); if (m_pixmap != nullptr) { delete(m_pixmap); m_pixmap = nullptr; } } PicWidgetManager::PicWidgetManager(QWidget* parent) : QWidget(parent) { this->setGeometry(0, 0, 1920, 1080); this->show(); } void PicWidgetManager::Init() { QImageReader::setAllocationLimit(0); PicWidget* pic1 = new PicWidget(this); PicWidget* pic2 = new PicWidget(this); PicWidget* pic3 = new PicWidget(this); m_pics.append(pic1); m_pics.append(pic2); m_pics.append(pic3); m_index = 0; pic1->Load("test.jpg"); } void PicWidgetManager::Start() { int next_index = (m_index + 1) % m_pics.size(); m_pics[next_index]->Load("test.jpg"); m_pics[next_index]->Play(); m_pics[m_index]->Stop(); m_index = next_index; QTimer::singleShot(3000, this, &PicWidgetManager::Start); }
#include <QApplication> #include "PicWidget.h" int main(int argc, char* argv[]) { QApplication a(argc, argv); PicWidgetManager manager; manager.Init(); manager.Start(); return a.exec(); }
If I remove m_widget, the switching is smooth.
-
@Quiccz said in Why is the display of a top-level transparent window slower?:
m_widget = new QWidget(nullptr);
m_widget->setGeometry(0, 0, 1920, 1080);
m_widget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
m_widget->setAttribute(Qt::WA_TranslucentBackground, true);
m_widget->hide();
this->setParent(m_widget);Why do you create a new widget and set it as parent of the PicWidget? PicWidget is already a QWidget.
"If I remove m_widget, the switching is smooth" - it is actually not needed at all because PicWidget is already a QWidget. -
@jsulm I know picwidget is already a QWidget, just because I need a top-level widget for all my item . picture, text, video...
https://forum.qt.io/topic/151608/how-to-overlay-transparent-areas-on-a-video-widget/3
I want to understand why the behavior is so strange, and I would like to fix it while keeping this architecture intact.
https://streamable.com/yyvuz4 -
@jsulm If I have two items, one is a video and the other is transparent text with a background. If both the video and text are placed under the same top-level widget, the transparent background of the text cannot overlay on top of the video. This causes the transparency of the background to be ineffective. However, if each item is placed under different top-level widgets, the issue does not occur. Therefore, I need m_widget.
The phenomenon shown in my other question is that a transparent widget is overlaid on top of the video, causing the display of the red background instead of the actual video.
translate from chatgpt -
@jsulm I understand what is troubling you, and I apologize. The normal practice I mentioned is to set the parent of the PicWidget, rather than setting it to nullptr.
PicWidget::PicWidget(QWidget* parent) : QWidget(parent) //: QWidget(nullptr) { /*m_widget = new QWidget(nullptr); m_widget->setGeometry(0, 0, 1920, 1080); m_widget->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); m_widget->setAttribute(Qt::WA_TranslucentBackground, true); m_widget->hide(); this->setParent(m_widget);*/ this->setGeometry(0, 0, 1920, 1080); this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); this->setAttribute(Qt::WA_TranslucentBackground, true); this->hide(); }
if set PicWidget parent as nullptr, it will flicker. and times must be picwidget's count() - 1.
At first, I thought that the initial delay in displaying the borderless top-level widget was causing the issue. However, even when I changed this->hide() to this->show(), it still flickers.The purpose of using m_widget is to confine all items within the same fixed area. This allows me to animate multiple items concurrently when they are placed in the same scene.And it will not cause the display to exceed the set range because they are independent widget.
-
When you want to stack widgets on each other use QStackedWidget.
-
@Christian-Ehrlicher use QStackedWidget means set parent for m_widget or PicWidget. I don't want it
-
Then you should blame your window manager that it can't show and hide top level widgets as fast as you like.
There is no reason to show and hide top level widgets that fast. Noone is doing this. -
@Christian-Ehrlicher Let m_widget show() when initialize fix it. top level widget seems neet time to show at first time.
-