Поместите прозрачный QWidget поверх QMediaView в QT5 на Ubuntu

цель

Я хочу, чтобы фон моего графического интерфейса на основе QT5 был видеофайлом, который играет. Я также хочу иметь возможность стилизовать мои компоненты GUI с прозрачностью, чтобы видео было видно через них.

Я не уверен, если это вообще возможно выполнить. Может быть, я просто пропустил важную подсказку (в конце концов, я новичок Qt), или может быть, что это просто не должно было работать. Но, будучи оптимистом, я отдал ему свое лучше попробуй.

первая попытка

моя минимальная первая попытка выглядела так:

int main( int argc, char **argv ){
    QApplication app(argc, argv);
    QMediaPlayer *media=new QMediaPlayer(0);
    QVideoWidget *video=new QVideoWidget(0); //new QGLWidget()
    media->setVideoOutput(video);
    media->setMedia(QUrl::fromLocalFile("/tmp/avatar.mp4"));
    media->setPosition(3000000);
    media->play();
    QPushButton *pb=new QPushButton(video);
    pb->setText(QString("BOB"));
    //pb->setStyleSheet(QString("background:transparent;"));
    video->show();
    return app.exec();
}

кнопка находится поверх воспроизводимого видео, что хорошо. Но если вы посмотрите внимательно, вы увидите несколько черных пикселей в углах кнопки, указывающих, что она не прозрачна над видео, а отображается как непрозрачный прямоугольник.

First result screenshot

вторая попытка

я попробовал стиль кнопки с background:transparent; (см. закомментированную строку в коде выше). Это сделало фон кнопки прозрачным, но черный ящик за кнопкой теперь еще более очевиден.

enter image description here

попытки

Я прочитал несколько советов из разных источников о том, как это сделать. На меня никто не работал. Я пробовал работать с QGraphicsScene и друзьями, различными стеками макетов, различными атрибутами на рассматриваемых виджетах и многими больше. Моей последней попыткой было установить родитель QVideoWidget на экземпляр QGLWidget () в надежде, что принудительное аппаратное ускорение решит мои проблемы (Мой компьютер имеет аппаратное 3D-ускорение с двоичным драйвером). Это просто остановило окно от появления вообще, в то время как я все еще мог слышать саундтрек видео, играющего в фоновом режиме, указывающий, что приложение все еще работает.

запрос

Я действительно надеюсь, что есть некоторые добросердечные и умные разработчики QT5, которые могут помочь мне выполнить мою мечту о виджетах, размещенных поверх воспроизведения видео в QT5 на Ubuntu.

спасибо!

3 ответов


Я знаю, что это старый вопрос, и вам удалось решить вашу проблему, преобразовав части вашего приложения в QML/QtQuick 2.2, но я в конечном итоге наткнулся на него с помощью поиска google, и кто-то еще с той же проблемой может также найти это. Я нашел решение, которое работало для меня и было протестировано на Windows с QT 5.3.

Я использовал QGraphicsView для отображения видео. Вот мой код (playerScreen-это QGraphicsView):

QGraphicsVideoItem *item = new QGraphicsVideoItem;
item->setSize(ui->playerScreen->size());
player.reset(new QMediaPlayer());
player->setVideoOutput(item);
QGraphicsScene *scene = new QGraphicsScene(0, 0, ui->playerScreen->size().width(), ui->playerScreen->size().height());
ui->playerScreen->setScene(scene);
ui->playerScreen->scene()->addItem(item);

Я отключил полосы прокрутки на экране playerScreen в противном случае были бы горизонтальные и вертикальные полосы прокрутки.

у меня есть QWidget поверх экрана playerScreen, в котором я рисую с QPainter. Этот QWidget находится поверх графического представления.

затем, когда я играю видео, я звоню ui->playerScreen-show(). Я делаю это только на play, потому что у меня есть другой экран сверху (для другого материала, связанного с моим проектом), и мне нужно вызвать show/hide, когда видео используется/не используется :)

Дайте мне знать, если вы нужна дополнительная информация о моем коде.


отказ от ответственности: я не пробовал это решение. Он работает на Qt 4.8, чтобы поместить транспарантные виджеты поверх всего, что отображается OpenGL. Я просто предполагаю, что media play использует аппаратное ускорение.

черные пиксели-это backbuffer Qt, где выполняется рендеринг программного обеспечения. Видео обходит этот backbuffer, и когда "обычный" виджет qt рисуется, он рисует поверх backbuffer, который все еще находится в исходном состоянии (черный).

вы можете сделать кнопку (или виджет, содержащий кнопку) отдельное, транспарантное окно.

setWindowFlags(Qt::FramelessWindowHint | Qt::SplashScreen);
setAttribute(Qt::WA_TranslucentBackground);

вам нужно будет расположить его вручную, поэтому он следует за вашим окном. Это означает, что кнопка должна установить eventfilter в окне и прослушивать любые события перемещения или изменения размера. Затем он пересчитывает свою собственную позицию относительно окна и обновляет ее.


qwidget4.1

void setAutoFillBackground (bool включен) //у вас есть этот метод, попробуйте.

всегда искать на форуме раньше, потому что есть много ответов. :) не то, что я против, это быстрее для вас.

виджет qt с полностью прозрачным фоном