QWidget mapToGlobal 和 mapToParent

写在前面

最近一个任务需要在界面(主窗口,顶级窗口,暂称为 c )中某个子控件(暂称为 a )位置显示一个自定义窗口(暂称为 b ),使用到了QWidget 的 mapToGlobal 和 mapToParent,做下简单总结。从QWidget 的 pos 说起。

一 QWidget

QWidget 是 Qt 中 GUI 对象的基类。 QWidget 的 pos 属性介绍如下:

This property holds the position of the widget within its parent widget
If the widget is a window, the position is that of the widget on the desktop, including its frame.
When changing the position, the widget, if visible, receives a move event (moveEvent()) immediately. If the widget is not currently visible, it is guaranteed to receive an event before it is shown.
By default, this property contains a position that refers to the origin.
Warning: Calling move() or setGeometry() inside moveEvent() can lead to infinite recursion.
See the Window Geometry documentation for an overview of geometry issues with windows.

Access functions:
QPoint pos() const
void move(int x, int y)
void move(const QPoint &)

即 pos 函数获得的是控件相对于父控件坐标系的位置。move 函数也是如此。

二  mapToGlobal 

QPoint QWidget::mapToGlobal(const QPoint &pos) const
Translates the widget coordinate pos to global screen coordinates. For example, mapToGlobal(QPoint(0,0)) would give the global coordinates of the top-left pixel of the widget.

初期方案中,将弹出的自定义窗口 b 设置为没有 parent,伪代码如下:

auto pos = a.pos();
auto p = a.parent.mapToGlobal(pos);
b.move(p);
b.show();

即直接从 a 的 parent 的坐标系中的坐标转换为 global 坐标系中坐标即可。

三  mapToParent

QPoint QWidget::mapToParent(const QPoint &pos) const
Translates the widget coordinate pos to a coordinate in the parent widget.
Same as mapToGlobal() if the widget has no parent.

任务后期发现,当自定义窗口 b 没有 parent 时, b的隐藏时机比较复杂,很难控制,所以改为将 b 的 parent 设置为主窗口 c 。然后发现 b 显示位置乱了。

其实此时 b 的 move 操作 是针对其 parent c 的坐标系来说的。那么问题变为:求解 a.parent 的坐标系的坐标 a.pos() 转换到 c 的坐标系的坐标是多少?伪代码如下:

auto pos = a.pos();
auto coordinate = dynamic_cast<QWidget*>(a.parent);
while (coordinate)
{
  pos = coordinate.mapToParent(pos);
  coordinate = dynamic_cast<QWidget*>(coordinate.parent);
}

b.move(pos);
b.show();

即不停的依靠 parent 转换 pos。此处注意,parent() 是 QObject 的函数,其返回值是 QObject*,而我们只需要调用mapToParent()函数,它是 QWidget 的函数,所以只需转换为 QWidget* 即可。向下转换用 dynamic_cast (C++ 语法)。

四 总结

总体来说 move 和 pos 都是相对于其父控件坐标系来说的,如果无parent (parent = 0),就是 global 坐标系。

move前, 先将坐标转换到对应坐标系的坐标。

五 参考

【参考Qt5.9.2 Assistant】

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值