Qt使用统一的坐标系统来定位窗口部件的位置和大小。
以屏幕的左上角为原点即(0, 0)点,从左向右为x轴正向,从上向下为y轴正向,这整个屏幕的坐标系统就用来定位顶层窗口;
此外,窗口内部也有自己的坐标系统,它依然以左上角作为原点,从左向右为x轴正向,从上向下为y轴正向,原点、x轴、y轴围成的区域叫做Client Area(客户区),在客户区的周围则是标题栏(Windows Title)和边框(Frame)。
有了Qt坐标系统的一些基础概念,那么具体该如何来进行窗口部件的定位呢?QWidget类,也就是所有窗口组件的父类都提供了成员函数来在坐标系统中进行定位。
从上图可以看出这些成员函数有三类:
——QWidget直接提供的成员函数:x()、y()获得窗口左上角的坐标,width()、height()获得客户区的宽和高
——QWidget的geometry()提供的成员函数:x()、y()获得客户区左上角的坐标,width()、height()获得客户区的宽和高
——QWidget的frameGeometry()提供的成员函数:x()、y()获得窗口左上角的坐标,width()、height()获得包含客户区、标题栏和边框在内的整个窗口的宽和高
测试程序:
#ifndef WIDGET_H #define WIDGET_H #include <QtGui/QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(); ~Widget(); }; #endif // WIDGET_H
#include "Widget.h" Widget::Widget() { } Widget::~Widget() { }
#include <QtGui/QApplication> #include <QPushButton> #include <QDebug> #include "Widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; QPushButton b(&w); b.setText("Button"); b.resize(, ); b.move(, ); //以Client Area左上角为(0, 0)点 w.resize(, ); //不同操作系统可能对窗口最小宽度有规定,若设置宽度小于规定值,则会以规定值进行显示 w.move(, ); //以屏幕左上角为(0, 0)点 w.show(); qDebug() << "QWidget"; qDebug() << w.x(); qDebug() << w.y(); qDebug() << w.width(); qDebug() << w.height(); qDebug() << "QWidget::geometry"; qDebug() << w.geometry().x(); qDebug() << w.geometry().y(); qDebug() << w.geometry().width(); qDebug() << w.geometry().height(); qDebug() << "QWidget::frameGeometry"; qDebug() << w.frameGeometry().x(); qDebug() << w.frameGeometry().y(); qDebug() << w.frameGeometry().width(); qDebug() << w.frameGeometry().height(); return a.exec(); }
输出结果:
在上面这个程序中,有两点需要补充说明:
第一,geometry()和frameGeometry()提供的坐标函数必须在show()调用之后使用才有效,否则会得到无效的数据;
第二,不同的操作系统可能对窗口的最小宽度有所规定,在使用void resize(int width, int height)设置顶层窗口大小时,若width小于规定的最小宽度,则会以规定的最小宽度进行显示,经个人测试,这个最小宽度对于win7 x64为116,对于win8.1 x64为160,因此在编写跨平台的程序时,有时候可能需要考虑到这个特性。
说到跨平台,这里还有一个问题:在不同的平台中(如windows和linux),窗口的外观式样是不一样的,这种差异体现在边框的宽度不一样、标题栏的宽度和高度不一样。Qt之所以在坐标系统相关的函数中,提供三组不同的函数出来,正是为了实现跨平台。
因为图形用户界面一般都是以像素为单位进行定位的,因此若想以跨平台的方式精确定位,就必须考虑到不同平台标题栏和边框的大小差异,QWidget围绕标题栏和边框提供的三组既相互联系又相互区别的函数,就可以解决这个问题。