关于使用DirectX在QGraphicsView上播放视频的探索

39 篇文章 0 订阅

最近注意到有人遇到了一个我半年前遇到的问题,我将半年前自己的探索写出来供大家参考,希望对大家有帮助,如果有错误的地方希望不吝指教。如果解决了问题,请告诉我。

大约半年前遇到了此问题,使用DirectX在QGraphicsView上播放视频。

由于当时项目比较急,一直没有解决。后来就换了QMdiarea代替了QGraphicsView框架,实现了directx通过窗口句柄(即WInId)播放视频的功能。


问题描述:使用QGraphicsProxyWidget 直接将一个视频窗口Widget加入 QGraphicsView,无法显示画面,不使用QGraphicsProxyWidget,视屏播放很正常


代码:

VideoMainWindow *videoWnd = new VideoMainWindow(); //播放视频的widget

    CustomProxy *proxyVideo = new CustomProxy;

    proxyVideo->setWidget(videoWnd);

    proxyVideo->setCacheMode(QGraphicsItem::DeviceCoordinateCache);

    _scene->addItem(proxyVideo);



如果去掉代理,视频正常,加上代理,只有窗口,不会显示画面。

在那几天我找到的唯一的相关的资料列举如下:


参考网址:(From:http://blog.csdn.net/ajaxhe/article/details/7316011#comments)

官方提供的小例子是入门的好资源
参考链接2http://blog.csdn.net/huihui1988/article/details/5725955
网友提供的一个Qt使用QGraphicsView实现滑动窗体效果,参考了有关QGraphicsView的使用。其实在官方提供的qmediaplayer可以正常显示视频,但加入QGraphicsView是为了在视频上输出一些其他的信息。
参考链接3提供了一个在VideoWidget上附着透明控件的思路,也是这篇文章让我尝试了QGraphicsView,效果良好,原理上可以解决我之前遇到的一个DirectDraw控制的widget上显示文字的问题(还没有来得及测试)。关于这个问题,请参考:http://www.qtcn.org/bbs/read.php?tid=47175

从链接2中,关于QGraphicsView与视频播放,但是只是用来输出一些其他信息,和winId没有任何关系,所以一直没有找到相关的任何资料。

当使用时可以判断出窗口句柄是可变的,如果窗口句柄发生了变化,DirectX所拥有的原来的窗口句柄就会变得无效,自然没有画面。
后来我发现有一个事件:QEvent::WinIdChange可以捕捉一个QWidget窗口句柄的变化。我没有去尝试。
先下班回家了,未完待续。。。
if (!q->isWindow()) { 
QWidget *parent = q->parentWidget(); 
也就是graphicsItem会一直向上找到isWindow()为true的窗体,然后返回此窗体的句柄,QGraphicsView框架所有的子项都是没有winid的,实际返回的应该是上层类的句柄,所以无法用direct渲染视频


后来只能看QGraphicsView源代码:

我发现QGraphicsProxyWidget 继承 QGraphicsItem 和 QObject,并非QWidget或QPaintDevice再看一下QGraphicsWidget的paintEvent手册文档:
void QGraphicsWidget::paintWindowFrame ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget *widget = 0 ) [virtual]
This virtual function is called by QGraphicsScene to draw the window frame for windows using painter, option, and widget, in local coordinates. The base implementation uses the current style to render the frame and title bar.
You can reimplement this function in a subclass of QGraphicsWidget to provide custom rendering of the widget's window frame.

这就说明ProxyWidget没有窗口句柄,而是渲染出来的
附上QWidget WinId代码:
WId QWidget::winId() const
{
    if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
#ifdef ALIEN_DEBUG
        qDebug() << "QWidget::winId: creating native window for" << this;
#endif
        QWidget *that = const_cast<QWidget*>(this);
#ifndef Q_WS_QPA
        that->setAttribute(Qt::WA_NativeWindow);
#endif
        that->d_func()->createWinId();
        return that->data->winid;
    }
    return data->winid;
}
void QWidgetPrivate::createWinId(WId winid)
{
    Q_Q(QWidget);


#ifdef ALIEN_DEBUG
    qDebug() << "QWidgetPrivate::createWinId for" << q << winid;
#endif
    const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
    if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
#ifndef Q_WS_QPA
        if (!q->isWindow()) {
            QWidget *parent = q->parentWidget();
            QWidgetPrivate *pd = parent->d_func();
            if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
                parent->setAttribute(Qt::WA_NativeWindow);
            if (!parent->internalWinId()) {
                pd->createWinId();
            }


            for (int i = 0; i < pd->children.size(); ++i) {
                QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
                if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
                                            || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
                    if (w!=q) {
                        w->create();
                    } else {
                        w->create(winid);
                        // if the window has already been created, we
                        // need to raise it to its proper stacking position
                        if (winid)
                            w->raise();
                    }
                }
            }
        } else {
            q->create();
        }
#else
        Q_UNUSED(winid);
        q->create();
#endif //Q_WS_QPA


    }
}


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值