【问题标题】:Put transparent QWidget on top of QMediaView in QT5 on Ubuntu在Ubuntu的QT5中将透明的QWidget放在QMediaView之上
【发布时间】:2013-05-29 03:58:55
【问题描述】:

目标

我希望基于 QT5 的 GUI 的背景是正在播放的视频文件。我还希望能够为我的 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();
}

按钮在播放视频的顶部,这很好。但是如果你仔细观察,你会在按钮的角落看到一些黑色像素,表明它在视频中不是透明的,而是呈现为一个不透明的矩形。

第二次尝试

我尝试使用background:transparent; 设置按钮的样式(参见上面代码中的注释行)。这使得按钮的背景透明,但按钮后面的黑框现在更加明显。

其他尝试

我已经从网上的各种来源阅读了一些关于如何做到这一点的提示。没有一个对我有用。我尝试过与 QGraphicsScene 和朋友一起工作,不同的布局堆栈,有问题的小部件上的不同属性等等。我最后一次尝试是将 QVideoWidget 的父级设置为 QGLWidget() 的一个实例,希望强制硬件加速能够解决我的问题(我的计算机具有带二进制驱动程序的硬件 3d 加速)。这只是完全阻止了窗口出现,而我仍然可以听到在后台播放的视频的配乐,表明应用程序仍在运行。

请求

我真的希望有一些善良和聪明的 QT5 开发人员可以帮助我实现在 Ubuntu 上将小部件放置在 QT5 播放视频顶部的梦想。

谢谢!

【问题讨论】:

  • 我几乎在所有方面都做了这个,我认为这是不可行的 - 从 QT 4.8 恕我直言,这是一个糟糕的回归。不过,我对您的问题给予了赏金,希望有人能启发我们……
  • 我也得出了同样的结论。从那以后(我不得不承认,我很不情愿地)将我的应用程序的一部分转换为 QML/QtQuick 2.2 来解决这个问题。这突然为我们打开了一个全新的灵活性和生产力世界。不幸的是,这也使我们的应用程序依赖于目标硬件上可用的 GPU 资源。这给我们带来了一些问题,但我们仍然很高兴已经皈依。感谢您的赏金!
  • 不幸的是,我无法转向 QML(插入 libvlc 原因)。有趣的是它的工作原理......最好的问候。

标签: c++ ubuntu video user-interface qt5


【解决方案1】:

我知道这是一个老问题,您设法通过将应用程序的部分转换为 QML/QtQuick 2.2 来解决您的问题,但我最终通过谷歌搜索遇到了它,其他有相同问题的人也可能会发现这个问题。我找到了一个对我有用的解决方案,并且已经在 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 上的滚动条,否则会有水平和垂直滚动条。

我在 playerScreen 顶部有一个 QWidget,我在其中使用 QPainter 进行绘制。该 QWidget 位于图形视图的顶部。

然后,当我播放视频时,我打电话给ui->playerScreen-show()。我只在播放时这样做,因为我在顶部有另一个屏幕(用于与我的项目相关的其他内容)并且我需要在使用/不使用视频时调用 show/hide :)

如果您需要有关我的代码的更多信息,请告诉我。

【讨论】:

  • 谢谢老兄!为了记录在案,在 s.o. 上热烈欢迎改进 uppon 或添加旧问题。 :-)
  • 不客气。如果你最终测试它,让我知道它对你有什么好处。 :)
  • 我会的。 ps:圣诞快乐
  • 很高兴听到那个参宿七! :)
【解决方案2】:

免责声明:我没有尝试过这个解决方案。它适用于 Qt 4.8,将透明的小部件放在任何 OpenGL 渲染的东西上。我只是假设媒体播放正在使用硬件加速。

黑色像素是执行软件渲染的 Qt 的后台缓冲区。视频绕过了这个后备缓冲区,当绘制“常规”qt 小部件时,它会在仍处于初始状态(黑色)的后备缓冲区之上进行绘制。

您可以使按钮(或包含该按钮的小部件)成为一个单独的透明窗口。

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

您需要手动定位它,因此它会跟随您的窗口。 这意味着按钮需要在窗口上安装一个事件过滤器,并监听任何移动或调整大小事件。然后它重新计算自己相对于窗口的位置,并更新它的位置。

【讨论】:

  • 在我的书中,这将被视为真正绝望的人(那些不能选择 QtQuick 的人)的 hack。因此,我不愿意接受这是正确的答案,至少在任何人能够真正确认它会起作用之前是这样。在实践中,这会将合成的全部责任转移给操作系统,这可能无法在所有情况下都可靠地工作。
【解决方案3】:

qwidget4.1

void setAutoFillBackground(bool enabled) //你有那个方法,试试看。

之前总是在论坛里搜索,因为有很多答案。 :) 我不介意,它对你来说更快。

A qt widget with fully transparent background

【讨论】:

  • 嗨!我想你可能很快就跳到了这个。你看,当我将它们绘制在其他小部件上时,这些按钮是透明的。背景视频是这里的罪魁祸首,因为显示视频的区域有一些硬件加速。在发布我的问题之前,我真的很努力地寻找解决方案,我也去过你建议的页面,这些都不是答案。
  • 好吧,我的错?我为你提供了你需要的东西,qt-project.org/doc/qt-5.0/qtwidgets/qwidget.html你没有完全阅读文档。您可以将一些渲染标志传递给您 qpushbutton 以获取父级的背景(如果不是特定的)。或者使用自定义 qpushbutton 并重新实现方法。感觉很懒...暂时没有代码。
  • 您是否阅读了您提供的链接?引用:“左侧小部件没有设置其他属性或小部件属性。此默认状态适合大多数使用透明度的自定义小部件,形状不规则,或者不使用不透明画笔在其整个区域上绘画”。我可以在我的代码中确认这一点,方法是将最上面的小部件从视频中移开并移到另一个小部件上,它看起来完全像它应该的那样,没有黑色背景矩形,让背景发光。我建议你自己试试:)
猜你喜欢
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多