Qt Widget重叠放置和兄弟Widget的事件传递
2016-12-21 12:12
120 查看
问题的提出
在项目中有一个要求:需将两个widget重叠放置,并且上面的widget为透明背景。解决方案
在谷歌搜索中找到一个比较可行的解决方案,利用QGridLayout布局管理器对象实现两个Widget的重叠放置。可以手动也可以利用QDesigner,将第一个widget加入到QGridLayout布局管理器对象中。
gridLayout->addWidget(widget_1, 0, 0, 1, 1);
第二个widget只能手动编码加入到QGridLayout中,并且和第一个widget放置在同一个单元格中,这样,第二个widget就可以重叠放置在第一个widget上面。
gridLayout->addWidget(widget_2, 0, 0, 1, 1);
问题的提出续
这样的确可以实现两个widget的重叠放置,但却带来了另一个问题,那就是底下的widget被上层的widget覆盖,底下的widget无法接受到任何事件通知了。解决方案续
在国内搜索到,有个牛叉的人提出了一个可行的方案。重载第一个widget的事件处理函数,将其接收的事件再转发给第二个widget(底下的widget)。以鼠标移动事件为例。void Widget_1::mouseMoveEvent(QMouseEvent *event) { QWidget::mouseMoveEvent(event); //第一个widget需要的事件 Process(event); //将事件传递给兄弟widget(底下的被覆盖的widget PostMouseEventToSiblings(event); } void Widget_1::PostMouseEventToSiblings(QMouseEvent *e) { if(this->parentWidget()) { this->setAttribute(Qt::WA_TransparentForMouseEvents, true); QPoint pt = this->mapTo(this->parentWidget(), e->pos()); QWidget *w = this->parentWidget()->childAt(pt); if (w) { pt = w->mapFrom(this->parentWidget(), pt); QMouseEvent *event = new QMouseEvent(e->type(), pt, e->button(), e->buttons(), e->modifiers()); QApplication::postEvent(w, event); } this->setAttribute(Qt::WA_TransparentForMouseEvents, false); } }
隐忧
我们在将事件传递给底下被覆盖的widget时,应用new运算符在堆上创建了一个QMouseEvent对象。熟悉Qt的都知道,父widget析构时会将其子对象一并析构掉。可是new出来的QMouseEvent并没有指定和加入到任何父widget当中,那它如何析构销毁呢,程序中也没有显示销毁的操作,这样会不会带来内存泄漏呢?定心丸
在Qt的帮助文档中,通过sendEvent和postEvetn的解读,找到了我们寻求的答案。sendEvent: Sends event event directly to receiver receiver, using the notify() function. Returns the value that was returned from the event handler. postEvent: Adds the event event, with the object receiver as the receiver of the event, to an event queue and returns immediately. The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is not safe to access the event after it has been posted.
意思就是,如果你使用sendEvent,必须由调用者来创建和销毁事件对象,所以此事件一般在栈上创建。
如果你使用postEvent,他是通过事件队列来管理的,一旦post之后,就由事件队列来负责事件对象的销毁,所以此时事件对象必须创建在堆上。
相关文章推荐
- *QT QGraphicsScene、QGraphicsItem、QGraphicsProxyWidget、QWidget间的事件传递
- Qt中父子widget的事件传递
- QT的父子Widget之间消息的传递(如果子类没有accept或ignore该事件,则该事件会被传递给其父亲——Qlabel与QPushButton的处理就不一样)
- QApplication向widget 传递的事件循序
- QT QGraphicsScene、QGraphicsItem、QGraphicsProxyWidget、QWidget间的事件传递
- Qt中父子widget的事件传递
- Qt中父子widget的事件传递
- 独立组件之间重叠放置时,OnTouch事件的响应顺序
- Linux input子系统分析 事件传递过程
- TouchEvent事件的传递
- OS开发 touch事件的优先级和事件传递
- 给dom事件方法传递参数,有多少种方法?
- Android Touch事件传递机制详解 下
- 史上最详细的iOS之事件的传递和响应机制-原理篇
- 关于Android触摸事件TouchEvent的传递及截取,研究心得。
- Android事件传递机制(一)
- Android 中Touch(触屏)事件传递机制
- 点击事件是如何传递给Activity的
- android事件传递全解析
- Android事件传递机制