起因
因为被分派了一个bug, 需要解决弹出的对话框居中问题. 一开始我还觉得这个问题很简单, 直接用move就行了, 奈何怎么都不能居中. 经过一系列测试发现, 在获取父窗口的大小时, 会发生变动, 导致计算总会有偏差. 最后去翻了一下QDialog的源码, 找到了这么一个方法
至此有了一个新的思路. 另外, 我也想起了侯捷大师的一句话: 源码之前, 了无秘密! 如果问题不能解决, 就多找找源码看看, 也许源码里面会有多种解决方法.
示例
通过这次修改bug, 我也在此总结一下目前我了解的一些移动控件位置的方法.
-
moveCenter
即, 移动控件的中心位置移动到指定点, 不会改变控件的大小. -
move
将控件的x,和y点移动至指定点 -
adjustPosition(这个方法, 是Qt内部的实现, 没有形成公共接口)
// 获取父窗口 auto w = qobject_cast<QWidget*>(this->parent()); QPoint p(0, 0); int extraw = 0, extrah = 0, scrn = 0; if (w) w = w->window(); // 获取实际桌面 QRect desk; if (w) { scrn = QApplication::desktop()->screenNumber(w); } else if (QApplication::desktop()->isVirtualDesktop()) { scrn = QApplication::desktop()->screenNumber(QCursor::pos()); } else { scrn = QApplication::desktop()->screenNumber(this); } desk = QApplication::desktop()->availableGeometry(scrn); QWidgetList list = QApplication::topLevelWidgets(); for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) { QWidget * current = list.at(i); if (current->isVisible()) { int framew = current->geometry().x() - current->x(); int frameh = current->geometry().y() - current->y(); extraw = qMax(extraw, framew); extrah = qMax(extrah, frameh); } } // sanity check for decoration frames. With embedding, we // might get extraordinary values if (extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40) { extrah = 40; extraw = 10; } if (w) { // Use mapToGlobal rather than geometry() in case w might // be embedded in another application QPoint pp = w->mapToGlobal(QPoint(0,0)); p = QPoint(pp.x() + w->width()/2, pp.y() + w->height()/ 2); } else { // p = middle of the desktop p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2); } // p = origin of this p = QPoint(p.x()-width()/2 - extraw, p.y()-height()/2 - extrah); if (p.x() + extraw + width() > desk.x() + desk.width()) p.setX(desk.x() + desk.width() - width() - extraw); if (p.x() < desk.x()) p.setX(desk.x()); if (p.y() + extrah + height() > desk.y() + desk.height()) p.setY(desk.y() + desk.height() - height() - extrah); if (p.y() < desk.y()) p.setY(desk.y()); move(p);