标题是非常的哗众取宠了。这里主要是用来记录一些使用 Qt 的小经验。之前在工作中,会有一些关于 Qt 的经验总结,加之平时自己写一些小东西也有使用 Qt ,所以使用起来会有一些经验教训,聚集起来,姑且叫做 Effective Qt 了。随时想到会随时更新内容。(注:这里会有一些代码设计的思路,不存在绝对的正误,只是一种习惯)
parentWidget() 方法获取 QWidget 指针强制转换为父控件指针,调用父对象方法。 在对子控件布局的时候,某些情况下实例化子控件时传递的父指针会被置空,例如对子控件设置一些特殊的窗口标志。
void paintEvent(QPaintEvent* e) 方法中的逻辑要避免出现间接调用 update() 方法。 由于 update() 方法与 repaint() 机制不同,所以当出现上述情况,并不会直接爆栈,迅速发现问题。而是在某些会导致频繁重绘的操作下,程序异常卡顿,但是不涉及重绘的操作,程序又看起来没问题。
static Qt 类型。 避免 Qt 类型的某些内容比 QCoreApplication 更早的初始化,导致一些数值异常。比如在更早的时机调用 QStyle::dpiscaled(),导致无法得到正确的系统DPI。connect() 方法的返回值,可以在 debug 时快速的发现自己的槽和信号没有正确的连接。adjustSize()、updateGeometry()以及sizeHint()是处理复杂界面布局变动的利器。 简单来说 adjustSize() 是根据子控件调整自己的大小,updateGeometry() 是根据自己的大小和子控件的大小调整子控件的布局。在处理复杂布局时,还需要配合每一个控件本身的 sizePolicy() 以及布局的 sizeConstraint() 方可显示出Qt动态布局的威力
updateGeometry() 并不是每次调用都一定会生效,有时候你需要 QLayout::invalidate() 来辅助你更新布局。 Qt只会在它觉得需要重新更新的时候才更新(具体的判断可以参考源码,大意是说调过了 setXXXSize() 这种方法以后,Qt才认为需要重新更新)。这个时候你可以选择拿到控件的 QLayout 然后循环对每个布局调用 QLayout::invalidate() ;在比较特殊的情况下你可以选择用 setFixedSize(sizeHint()) 这种奇怪的调用代替循环,当然请在你非常熟悉你在做什么的时候才去用这种方式代替循环。
QLayout 来控制控件的位置,而不是套用一个又一个的 QWidget ,因为永远不能预料到产品会把一个页面上的哪两个控件联系在一起,如果这些控件相隔了几个 QWidget ,拿到它们的指针将是一件非常蛋疼的事未完待续……