• 13597阅读
  • 11回复

如何让QGraphicsProxyWidget的子类接受到dropEvent(问题解决,讨论可继续) [复制链接]

上一主题 下一主题
离线sbtree
 
只看楼主 倒序阅读 楼主  发表于: 2009-10-23
— 本帖被 XChinux 从 General Qt Programming 移动到本区(2011-01-02) —
写了一个继承QGraphicsProxyWidget的子类,想在dropEvent中处理一些个性化的操作。
最初的尝试:首先在该子类的构造函数中调用了setAcceptDrops(true),然后重写dropEvent函数,程序运行后发现,dropEvent函数根本不能被触发,连界面上都不能出现像带小加号的鼠标(对于一般的QGraphicsItem的子类,当鼠标拖拽到该组件上的时候,鼠标会带一个小加号表示拖拽的东西可以由该组件接受。)
进一步的尝试:对在QGraphicsProxyWidget子类中加载的Widget安装事件过滤器,并重新写了QGraphicsProxyWidget子类的eventFilter函数,使其所有的事件都转发给QGraphicsProxyWidget子类,观察发现,QGraphicsProxyWidget子类可以接受到包括DragEnter这样的事件,却没有Drop事件,苦恼中。。。
[ 此帖被sbtree在2009-10-29 20:23重新编辑 ]
windows 7 + VC++2008 + Qt4.5.2
离线dashanda
只看该作者 1楼 发表于: 2009-10-23
把setflag(true)改为setflag(false)
离线sbtree
只看该作者 2楼 发表于: 2009-10-23
引用第1楼dashanda于2009-10-23 20:16发表的  :
把setflag(true)改为setflag(false)

你说的是哪个flag?QGraphicsItem::ItemStacksBehindParent?试了,好像不管用
windows 7 + VC++2008 + Qt4.5.2
离线sbtree
只看该作者 3楼 发表于: 2009-10-23
目前我只对QGraphicsProxyWidget子类设置了QGraphicsItem::ItemIsSelectable
windows 7 + VC++2008 + Qt4.5.2
离线sbtree
只看该作者 4楼 发表于: 2009-10-26
dashanda怎么不来回答了?
windows 7 + VC++2008 + Qt4.5.2
离线hiti_tony
只看该作者 5楼 发表于: 2009-10-27
试试setAcceptDrops(true);
离线sbtree
只看该作者 6楼 发表于: 2009-10-28
慢慢的发现,这个问题不是那么简单解决的,这里涉及到很多事件相关的内容,包括事件被截获,顶层部件,事件机制,尤其在graphics view and scene框架中还有其特殊性,特别是那些继承了QObject的 QGraphicsItem,很多事件不知道被怎么处理掉了,即使安装了事件过滤器也不能把所有的事件都截获到。还有一个奇怪的事情,qt中对QGraphicsItem另作了一个事件过滤器,sceneEventFilter,这个过滤器没有和QObject::eventFilter协调起来,对于继承了QObject的 QGraphicsItem在处理事件的时候造成了很多无法处理的问题,包括我在帖子里提到的dropEvent执行不到的问题(其实还有很多其他的事件存在类似的问题)。要想彻底解决这个问题,看来必须研究研究graphics view and scene框架的源码了,有相关需求的网友不妨一起讨论,共同进步。
这里再提及一下QGraphicsItem为什么没有继承QObject,而是另起炉灶,重做了一个基类呢? 我觉得这是qt设计是的一个失误,它舍弃了QObject本来有的信号与槽的良好机制,而在后续的版本中又勉为其难的加入了QGraphicsWidget,QGraphicsProxyWidget等类来作补充,至此造成了事件处理过程中无法协调的问题。这个问题应该让Nokia好好反思一下。
windows 7 + VC++2008 + Qt4.5.2
离线hiti_tony
只看该作者 7楼 发表于: 2009-10-28
........
离线sbtree
只看该作者 8楼 发表于: 2009-10-29
Re:如何让QGraphicsProxyWidget的子类接受到dropEvent(问题解决)
经过多方研究终于发现了解决这个问题的方法,写出来希望对有类似问题的朋友能有所帮助,这是在帮助文档中没有讲到的
QGraphicsProxyWidget的子类除了要重写dropEvent函数和显示地调用setAcceptDrops(true)之外,对其内嵌的widget要重新实现3个函数,dragEnterEvent,dropEvent和dragMoveEvent,前两个在帮助文档中明确写明了,只要实现就可以使用drag and drop系统,其实这仅仅适用于一般的窗口部件,而对于嵌入到QGraphicsProxyWidget或其子类中的窗口部件,必须实现第三个 dragMoveEvent(这一点我翻遍帮助文档也没有找到),而在嵌入的widget是否需要实现dropEvent依赖于QGraphicsProxyWidget的子类是否实现了这个事件函数,如果QGraphicsProxyWidget的子类实现了,嵌入的窗口部件就不一定非要实现这个事件函数,当然嵌入的widget的setAcceptDrops(true)函数也必须显示的被调用。
windows 7 + VC++2008 + Qt4.5.2
离线sbtree
只看该作者 9楼 发表于: 2009-10-29
进一步发现QGraphicsScene的子类也存在类似的问题。
比较一下model/view框架和scene/view框架,其实他们有很多相似的地方,而在设计时对于事件的处理却使用了两套完全不兼容的函数名称,例如sceneEvent与event,sceneEventFilter与eventFilter等,似乎走了两条路线,希望在不久的将来,Nokia能将这两条路线合二为一,这样会解决很多兼容性的问题。
windows 7 + VC++2008 + Qt4.5.2
离线hrgstephen
只看该作者 10楼 发表于: 2010-01-26
真是感谢楼上,这个问题我困扰了一天,百思不得其解,在这里得到了解决方法!确实是需要实现 QDragMoveEvent 才行,这个在书上和文档里都没有提到,书上说一般只要实现 QDragEnterEvent 和 QDropEvent 就行了,事实上还需要  QDragMoveEvent (对某些控件)
离线weinkym

只看该作者 11楼 发表于: 2013-08-12
我是继承了QGraphicsView,当时只实现
virtual void dragEnterEvent(QDragEnterEvent* event);    virtual void dropEvent(QDropEvent* event);

这两个是无法 进入dragMoveEvent
后来加了
virtual void dragMoveEvent(QDragMoveEvent *event);
就可以进入了
void ZCurveView::dragMoveEvent(QDragMoveEvent *event);
void ZCurveView::dragMoveEvent(QDragMoveEvent *event)
{
    event->acceptProposedAction();
}

快速回复
限100 字节
 
上一个 下一个