找回密码
 立即注册
收起左侧

让QWindow支持拖放的方法

4
回复
1383
查看
[复制链接]
累计签到:796 天
连续签到:3 天
来源: 原创 2018-12-25 10:57:37 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 一叶知秋 于 2018-12-25 11:10 编辑

这个需求可能并不是太常见,希望给有需要的人抛砖引玉吧

其实并不是真的让QWindow支持拖放,文档里没这接口,我也尝试了native的方法,没用。。。

可能是我对windows系统API不熟吧,反正最后没搞起来

因为项目里有个需求要使用实时视频,底层库需要个窗口WIND来给它渲染,这个地方历经三次改版,前后一年左右。。。

现在总算有了还不错的解决方案


解决方案一:

使用QWidget,然后给其加属性

    setAttribute(Qt::WA_NativeWindow);

    setAttribute(Qt::WA_DontCreateNativeAncestors);

然后main函数里还要给QApplication加

    app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);

这样就可以用起来,当然里面还有一些小细节,就不一 一赘述了。。。

总结:这种解决方案,可以有较多的控制,因为是QWidget,所以可以做很多操作和效果。此前很长时间里都是使用这种解决方案,

但是在做一机三屏的过程中,发现整个视频调度窗口被移到另外一个屏幕后,渲染就一直只在那个位置渲染了,切回主屏的时候没画面。

而且会造成Qt5Gui库崩溃,没有任何提示,一脸懵逼。。。

最后定位到是加了 setAttribute(Qt::WA_DontCreateNativeAncestors); 这个属性导致的,但是至于是为什么,没有去看源码。。。

我想升级到VS2015 + Qt5.9.7尝试是否能够解决,但是底层库还没准备好,现在还没试,所以就有了解决方案二


解决方案二:


使用QWindow,然后通过QWidget封装QWindow进行操作,这样就不需要设置各种属性了,使用起来方便许多,示例代码如下

    mSurfaceWindow = new BTSurfaceWindow();

    QWidget* windowContainer = createWindowContainer(mSurfaceWindow, this);

我们直接在以QWidget为基础的程序里嵌入windowContainer就可以了

本来以为到此完美解决问题,最后发现QWindow不支持拖放,因为我们的需求里要拖动调换窗口位置。。。。。。

最后经过两天的折腾,尝试各种解决方法,还好没有随便放弃,最后灵光乍现,既然拿到了windowContainer ,

为什么不安装个事件过滤器试试,还真行,哈哈。。。

    windowContainer->setAcceptDrops(true);

    windowContainer->installEventFilter(this);

这样事情总算有个圆满解决了,其实中间还有一些小细节,就不一 一赘述了。。。

总结:这种方案解决了一机三屏问题,效果也不错,是我目前使用的方案。

但是需要注意性能问题和使用上的注意事项,在QWidget::createWindowContainer文档里已有详细描述,比如

  • Using many window container instances in a QWidget-based application can greatly hurt the overall performance of the application.

综上所述可以根据自己项目的实际情况选择合适的方案,也欢迎大家批评指正,提供更好的解决方案。


回复

使用道具 举报

累计签到:796 天
连续签到:3 天
2018-12-29 11:46:25 显示全部楼层
重新实现QWindow的event函数自己处理也是可以的。。。
回复 支持 反对

使用道具 举报

累计签到:1 天
连续签到:1 天
2019-1-9 18:26:10 显示全部楼层


头文件加几句代码搞定
protected:
        void mousePressEvent(QMouseEvent *event) {
                windowPos = this->pos();
                mousePos = event->globalPos();
                dPos = mousePos - windowPos;
        }
        void mouseMoveEvent(QMouseEvent *event) {
                this->move(event->globalPos() - this->dPos);
        }
        QPoint windowPos;
        QPoint mousePos;
        QPoint dPos;

点评

是拖放不是拖动,drag & drop  详情 回复 发表于 2019-1-10 09:18
回复 支持 反对

使用道具 举报

累计签到:796 天
连续签到:3 天
2019-1-10 09:18:00 显示全部楼层
chifandeyu 发表于 2019-1-9 18:26
头文件加几句代码搞定
protected:
        void mousePressEvent(QMouseEvent *event) {

是拖放不是拖动,drag & drop  
回复 支持 反对

使用道具 举报

累计签到:1 天
连续签到:1 天
2019-1-10 16:05:18 显示全部楼层
本帖最后由 chifandeyu 于 2019-1-10 16:10 编辑
一叶知秋 发表于 2019-1-10 09:18
是拖放不是拖动,drag & drop

好吧 大佬 佩服你了 你这方法多多, 说到拖放窗口,我之前用的是重写notify函数实现啵
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册