Ниже я расскажу, почему это проблематично сделать, и какой workaround я нашел.
Проблема состоит в том что phonon-backend, например GStreamer рисует видеоряд в Linux напрямую через XRender, путем длительного гугления и всяческих тестов я убедился, что невозможно вывести прозрачный QWidget поверх видеоряда, в любом случае получается черная подложка. Т. е. изначально, я пробовал такой вариант кода:
- m_video = new Phonon::VideoWidget;
- .....
- view->setHtml("<div style=\"color:#FFFFFF;font-size:36px;\">Hello Qt!</div>");
- view->setPalette(palette);
- m_video->show();
- m_video->resize(640, 480);
- view->setFixedSize(m_video->width(), m_video->height());
ЭТОТ ВАРИАНТ НЕ РАБОТАЕТ!
Тогда я решил попробовать поискать обходной путь и нашел его. Основная идея в том чтобы сделать оверлейный виджет отдельным окном с отключенным оформлением, причем такой, чтобы он был привязан к VideoWidget таким образом, чтобы мог перемещаться и менять размеры вслед за ним.
Сначала наследуем новый класс от видео виджета и переопределяем event методы таким образом, чтобы автоматически изменять геометрию оверлейного виджета в зависимости от геометрии видео виджета:
- class OverlayedVideoWidget : public Phonon::VideoWidget
- {
- public:
- Phonon::VideoWidget(parent),
- m_overlayWidget(0)
- {
- }
- {
- m_overlayWidget = widget;
- }
- protected:
- {
- if (m_overlayWidget)
- m_overlayWidget->move(event->pos());
- }
- {
- if (m_overlayWidget)
- m_overlayWidget->resize(event->size());
- }
- {
- if (m_overlayWidget)
- m_overlayWidget->hide();
- }
- {
- if (m_overlayWidget)
- m_overlayWidget->show();
- }
- {
- if (m_overlayWidget)
- m_overlayWidget->close();
- }
- private:
- };
Таким образом мы добиваемся того, чтобы оверлейный виджет всегда находился над виджетом с видеорядом и имел точно такие же размеры.
А теперь подключаем виджет:
- m_video = new OverlayedVideoWidget;
- view->setHtml("<div style=\"color:#FFFFFF;font-size:36px;\">Hello Qt!</div>");
- view->setPalette(palette);
- view->page()->setPalette(palette);
- m_video->setOverlayWidget(view);
- m_video->show();
- m_video->resize(640, 480);
Вся соль идеи в 11 и 12 строках. Мы делаем оверлейный виджет окном специального типа, который не имеет заголовка, не отображается в панели задач и имеет прозрачный background.
Поскольку наше "окно" привязано к OverlayedVideoWidget оно все время будет как бы парить над ним, создавая эффект единого целого.
На этом все.
No comments:
Post a Comment