QT中的QLayout对控件的调整是异步进行的 - sbw Blog

QT中的QLayout对控件的调整是异步进行的

来源: 石博文博客 | 浏览: 9100 | 评论: 4 发表时间: 2014-01-21

今天用QT写了个扫雷小游戏,界面和功能都是按照WindowsXp下面的winmine来做的,因为需要Press,Release和Click这些事件,索性我就用QPushButton来做的那些小方块,把它们的Text设为空,只显示Icon,并用QGridLayout来对它们布局.但我想在QGridLayout对Button进行Resize后重新得到Button的Size,问题就出现了,我获取到了640*480这个大小.



一开始,我把setIcon放在了QPushButton的resizeEvent事件里,在Button的大小发生变化后重新Scale图片然后setIcon.


后来我发现因为所有的Button大小都一样,这样写每个Button都有一个独立的QPixmap,内存占用很大,于是我就准备把图片在Button Resize之后处理,然后一个个Blit到Button上,也就是所有Button只用了同一张图片.然后就有了下面这样的代码:


在更新完所有控件之后,我准备获取0号Button的Size来Scale图片,但是我发现虽然界面上看起来Button已经被布局管理器调整了大小,但如果此时我获取Button的属性,得到的却是640*480这个大小.


之后,我在qDebug()函数前面加了1秒的延时,这时再调用0号Button的Width()和Height()就能得到正确的大小了,为了进一步验证,我自己写了个类继承QPushButton,重写了resizeEvent函数,发现resizeEvent确实被调用了,而且确实是在qDebug()之后被调用的.也就是说,当执行到qDebug()这里时,QGridLayout其实还没有对其中的控件进行布局.由此可以猜测QGridLayout对控件的布局可能是异步进行的.


于是我Google了各种关键词,查了好多QT文档都没有发现什么结果(而且发现Nokia的QT网站进不去了).


什么也找不到,只能自己慢慢查了,下载了QT的源代码,我先查了QGridLayout的代码:


发现在它的底层调用了addChildWidget和addItem这两个方法.addItem是QGridLayout中的,所以应该是网格布局特有的一些东西,addChildWidget是继承来的,而且没有被重写.于是我又查了它的父类QLayout,找到了addChildWidget这个方法的实现:


addChildWidget会先把原来的对象重新设置父控件,并且根据它的isVisiable和isHidden等属性确定这个控件是否能显示出来,如果需要显示,会调用QMetaObject::invokeMethod这个方法.看到后面那个调皮的//show later,我就知道这应该就是异步调整控件的地方了.


查询了QMetaObject::invokeMethod这个方法,它可以调用一个object对象的SIGNAL或者SLOT方法(object是QT中所有对象的祖先类),第二个参数是方法名,第三个为调用方式,Qt:: QueuedConnection便是将调用事件加入到主事件队列中(后面还有一些可省略参数,具体大家可以查文档),到此总算是破案了,可以说QT所有基类是QLayout的布局管理器都是异步实现的控件调整.


由此我想到了之前用到的QT的HTTP请求也是异步进行的,弄成异步的好处当然是可以提升运行效率,但由于QT的文档各种不全(感觉不光是QT,所有C++库文档都不如Java来的好),有些细节的遗漏总是会造成奇怪的问题:)




  • 声明: 评论属于其发表者所有,不代表本站的观点和立场.
  • qt 回复该留言 时间: 2014-02-16

    有一次我对listWidget加一条spin以调整大小时候也发现这个了。 于是我对listWidget重写resizeEvent然后emit一个信号实现

  • 石博文 回复该留言 时间: 2014-02-17

    嗯,我最后的解决办法是和Layout一样,使用[color: Red]QMetaObject::invokeMethod[/color]把事件加入主事件队列中,由于是在Layout之后添加的,就能保证这个事件执行时一定已经完成布局.

已有 2 位网友发表了一针见血的评论,你还等什么?
  • 昵称: *
  • 邮箱:
  • 网址:
  • 记住我的信息
  • Color
  • Red
  • Blue
  • Code
  • bash
  • cpp
  • css
  • java
  • js
  • perl
  • php
  • python
  • ruby
  • sql
  • xml