深度探索QT窗口系统——几何篇

窗口作为界面编程中最重要的部分,没有窗口就没有界面,是窗口让我们摆脱了DOS时代,按钮是一个窗口,文本框是一个窗口,标签页是一个窗口。一个窗口可以由多个窗口组成,每天我们都在与窗口打交道,当你打开windows时,桌面就是一个窗口,你打开浏览器时,你也正在访问窗口。QT窗口系统,QT是一个跨平台的框架,类似微软的MFC,Borland的OWL,前者只适用于windows,而使用QT你可以开发windows平台应用程序,你也可以开发linux应用程序,当然了你也可以用于Symbian、Meego的开发,据说,QT未来还会支持Android,iOS等操作系统。更让人欣喜的是,QT是开源的,你可以看到所有QT的源代码,而且帮助文档很详细,可以说,QT是一个很有前途的开发框架,如果大家想要转到QT平台做开发,深入了解QT的窗口系统是很有必要的。

QWidget的是所有窗体的基类,按钮,文本框,对话框都派生自它,所以了解它的特性后,所有窗体的基本属性都了解了。

1. Qt窗体的几何属性

下图是典型的QT窗口:

灰色部分是窗体的边框,白色区域为窗口的内容区域,绿色区域为窗口标题,QWidget提供1组接口访问窗口的几何特性:

  1. 包含窗口边框的函数: x(), y(), frameGeometry(), pos(), 和 move()
  2. 不包含窗口边框的函数: geometry(), width(), height(), rect(), 和size()

下面用一个实例来说明窗口这几个几何特性:

void print(QWidget *pWidget)

{

qDebug() << "this includes the window frame";

qDebug() << "frameGeometry() = " << pWidget->frameGeometry();

qDebug() << "pos() = " << pWidget->pos();

qDebug() << "x() = " << pWidget->x() << "y() = " << pWidget->y();

qDebug() << "frameSize() = " << pWidget->frameSize();

qDebug() << "this excludes the window frame";

qDebug() << "geometry() = " << pWidget->geometry();

qDebug() << "rect() = " << pWidget->rect();

qDebug() << "contentRect() = " << pWidget->contentsRect();

qDebug() << "width() = " << pWidget->width() << "height() = " << pWidget->height();

qDebug() << "size() = " << pWidget->size();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

widget.resize(200, 300);

widget.show();

print(&widget);

return a.exec();

}

显示的窗体大小为,宽为200,高为300,注意,这里的尺寸是相对电脑的屏幕分辨率来说的,也即单位为像素,下面是输出结果:

this includes the window frame

frameGeometry() = QRect(88,116 208x334)

pos() = QPoint(88,116)

x() = 88 y() = 116

frameSize() = QSize(208, 334)

this excludes the window frame

geometry() = QRect(92,146 200x300)

rect() = QRect(0,0 200x300)

contentRect() = QRect(0,0 200x300)

width() = 200 height() = 300

size() = QSize(200, 300)

可以看到包括边框的矩形宽度为208,高度为334;不包括边框的矩形宽度为200,高度为300,这正是我们通过resize设置的尺寸,由上图的窗口图形,不难得出,边框的宽度为4,标题的高度为26。

通过上面的介绍,我们知道了窗体的基本几何属性,也知道怎么去获取这些属性,QWidget有没有提供设置这些属性的方法呢?边框的宽度始终是4吗?标题的高度始终是26吗?有没有办法设置边框的宽度呢?有没有办法设置标题的高度呢?

如何设置窗口的几何特性,窗口的平移,窗口的缩放,如何去掉窗口的边框,如何去掉窗口的标题,如何限定窗口的尺寸,下面逐一介绍:

1. 窗口平移可以用如下两种方式来实现,一是通过move的方法,二是通过setGeometry的方法:

void move(int x, int y)

void move(const QPoint &pos)

void setGeometry(int x, int y, int w, int h )

void setGeometry(const QRect &rect);

对于采用move的方法来移动窗口,只能改变窗口的位置,不能改变窗口的大小,窗口的位置包括窗口边框,若窗口无父窗口,则位置坐标(x,y),相对于电脑屏幕来说的,若窗口有父窗口,则位置坐标(x,y)是相对于父窗口来说的;对于采用setGeometry的方法来移动窗口,可以改变窗口的位置的同时,改变窗口的尺寸,窗口的位置不包括窗口边框,若窗口无父窗口,则位置坐标(x,y)相对于电脑屏幕来说的,若窗口有父窗口,则位置坐标(x,y)相对于父窗口来说的;我们来看实例:

(1) 采用move的方法,窗口无父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "pos() = " << pWidget->pos();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

widget.show();

widget.resize(200, 300);

widget.move(0, 0);

print(&widget);

widget.move(100, 100);

print(&widget);

return a.exec();

}

widget先move(0,0)到屏幕的左上角,窗口系统的坐标轴x轴正向向右,y轴的正向向下,所以坐标原点在左上角;然后widget移动到move(100,100)的位置,下面是打印出的位置:

pos() = QPoint(0,0)

pos() = QPoint(100,100)

(2) 采用setGeometry 的方法,窗口无父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "pos() = " << pWidget->pos();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

widget.show();

widget.resize(200, 300);

widget.setGeometry(0, 0, 200, 300);

print(&widget);

widget.setGeometry(100, 100, 200, 300);

print(&widget);

return a.exec();

}

我们先来看打印出的结果:

pos() = QPoint(-4,-30)

pos() = QPoint(96,70)

为什么第一次不是移动到(0, 0),第二次不是移动到(100,100)呢?因为通过setGeometry设置的移动位置不包括边框,而我们打印出来的是边框的位置,参照几何篇1,很快你就知道,4是边框宽度,30是窗口标题高度+边框宽度。

(3) 采用move的方法,窗口有父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "pos() = " << pWidget->pos();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget parentWidget;

QPushButton *ppbTest = new QPushButton("test button", &parentWidget);

parentWidget.show();

parentWidget.resize(200, 300);

ppbTest->move(100, 100);

print(ppbTest);

ppbTest->move(0, 0);

print(ppbTest);

return a.exec();

}

ppbTest是parentWidget的子窗口,这次移动ppbTest,首先移动位置(100,100)处,然后移动到(0,0)处,先来看看输出结果:

pos() = QPoint(100,100)

pos() = QPoint(0,0)

通过上面的输出结果,我们不难得出结论,ppbTest子窗口move位置是相对父窗口parentWidget来说的,且是相对父窗口的内容矩形来讲的。

(4) 采用setGeometry的方法,窗口有父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "pos() = " << pWidget->pos();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget parentWidget;

QPushButton *ppbTest = new QPushButton("test button", &parentWidget);

parentWidget.show();

parentWidget.resize(200, 300);

ppbTest->setGeometry(100, 100, ppbTest->width(), ppbTest->height());

print(ppbTest);

ppbTest->setGeometry(0, 0, ppbTest->width(), ppbTest->height());

print(ppbTest);

return a.exec();

}

输出结果同(3),为什么呢?不是说setGeometry的移动起始位置不包括边框吗?怎么输出结果和(3)相同呢?这是在这里ppbTest没有边框的原因。

窗口缩放方法,然后介绍一个窗口慢慢展开和慢慢隐藏的实例,窗口缩放的方法有2种,一种是采用resize的方式,另一种是采用setGeometry的方式,下面是QT提供的对应函数接口:

void resize(const QSize &size)

void resize(int w, int h)

void setGeometry(int x, int y, int w, int h)

void setGeometry(const QRect &rect)

(1) resize方法,窗口没有父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

widget.show();

widget.resize(10, 10);

print(&widget);

widget.resize(116, 10);

print(&widget);

widget.resize(200, 300);

print(&widget);

return a.exec();

}

下面是输出结果:

geometry() = QRect(48,88 115x10)

geometry() = QRect(48,88 116x10)

geometry() = QRect(48,88 200x300)

为什么resize(10, 10)以后,geometry的宽度没有变为10呢,这是因为对有边框窗口,窗口上有图标,最小化,最大化,关闭按钮也需要空间,而这里的这下所需的最小空间为115,因此小于115,宽度都会是115。

(2) resize方法,无边框窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget(NULL, Qt::FramelessWindowHint);

widget.show();

widget.resize(10, 10);

print(&widget);

widget.resize(116, 10);

print(&widget);

widget.resize(200, 300);

print(&widget);

return a.exec();

}

下面是输出结果:

geometry() = QRect(256,231 10x10)

geometry() = QRect(256,231 116x10)

geometry() = QRect(256,231 200x300)

(3) resize方法,窗口有父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

QPushButton *ppbTest = new QPushButton("test button", &widget);

widget.show();

widget.resize(200, 300);

ppbTest->resize(10, 10);

print(ppbTest);

ppbTest->resize(116, 10);

print(ppbTest);

ppbTest->resize(200, 300);

print(ppbTest);

return a.exec();

}

下面是输出结果:

geometry() = QRect(256,231 10x10)

geometry() = QRect(256,231 116x10)

geometry() = QRect(256,231 200x300)

(4) setGeometry方法,窗口无父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

widget.show();

int x = widget.geometry().x();

int y = widget.geometry().y();

widget.setGeometry(x, y, 10, 10);

print(&widget);

widget.setGeometry(x, y, 116, 10);

print(&widget);

widget.setGeometry(x, y, 200, 300);

print(&widget);

return a.exec();

}

下面是输出结果:

geometry() = QRect(92,146 115x10)

geometry() = QRect(92,146 116x10)

geometry() = QRect(92,146 200x300)

(5) setGeometry方法,无边框窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget(NULL, Qt::FramelessWindowHint);

widget.show();

int x = widget.geometry().x();

int y = widget.geometry().y();

widget.setGeometry(x, y, 10, 10);

print(&widget);

widget.setGeometry(x, y, 116, 10);

print(&widget);

widget.setGeometry(x, y, 200, 300);

print(&widget);

return a.exec();

}

下面是输出结果:

geometry() = QRect(256,231 10x10)

geometry() = QRect(256,231 116x10)

geometry() = QRect(256,231 200x300)

(6) setGeometry方法,有父窗口

#include <QtGui/QApplication>

#include <qwidget.h>

#include <qdebug.h>

void print(QWidget *pWidget)

{

qDebug() << "geometry() = " << pWidget->geometry();

}

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget widget;

QPushButton *ppbTest = new QPushButton("test button", &widget);

widget.show();

int x = ppbTest->geometry().x();

int y = ppbTest->geometry().y();

widget.resize(200, 300);

ppbTest->setGeometry(x, y, 10, 10);

print(ppbTest);

ppbTest->setGeometry(x, y, 116, 10);

print(ppbTest);

ppbTest->setGeometry(x, y, 200, 300);

print(ppbTest);

return a.exec();

}

下面是输出结果:

geometry() = QRect(0,0 10x10)

geometry() = QRect(0,0 116x10)

geometry() = QRect(0,0 200x300)

前面从6个方面讲了通过resize和setGeometry对窗口缩放的方法,接下来给1个窗口展开和收缩的实例:

#ifndef _TEST_H

#define _TEST_H

#include <qwidget.h>

#include <qpushbutton.h>

#include <QTimerEvent>

class CExpandCollapseWidget : public QWidget {

Q_OBJECT

public:

CExpandCollapseWidget(QWidget *parent = NULL) : QWidget(parent, Qt::FramelessWindowHint)

{

timerId = 0;

bExpand = true;

ppbExpandCollapse = new QPushButton("Expand", this);

connect(ppbExpandCollapse, SIGNAL(clicked()), this, SLOT(rxClicked()));

}

protected:

void timerEvent(QTimerEvent *event)

{

if (event->timerId() == timerId)

{

int x = geometry().x();

int y = geometry().y();

int w = geometry().width();

int h = geometry().height();

setGeometry(x, y, w, h + increment);

if (bExpand)

{

if (h > 300)

{

killTimer(timerId);

timerId = 0;

}

}

else

{

if (h < 40)

{

killTimer(timerId);

timerId = 0;

}

}

}

}

private slots:

void rxClicked()

{

if (timerId == 0)

timerId = startTimer(10);

if (ppbExpandCollapse->text() == "Expand")

{

bExpand = true;

ppbExpandCollapse->setText("Collapse");

increment = 10;

//setSizeIncrement(0, 10);

}

else

{

bExpand = false;

ppbExpandCollapse->setText("Expand");

increment = -10;

}

}

private:

QPushButton *ppbExpandCollapse;

bool bExpand;

int timerId;

int increment;

};

#endif

上面是实现展开和收缩的例子,给出调用:

#include <QtGui/QApplication>

#include "test.h"

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

CExpandCollapseWidget widget;

widget.show();

return a.exec();

}

下面是运行结果:

当单击Expand按钮时,窗口呈现右边展开时的状态,当单击右边Collapse按钮时,窗口呈现左边收缩时候的状态。

如何去掉窗口边框?怎么限定窗口的大小?

首先来看第一个问题:

1. 有父窗口的的窗口,自动变为无边框窗口

2. 无父窗口,加Qt::FramelessWindowHint标志(Qt3.0以上的版本)

QWidget widget(NULL, Qt::FramelessWindowHint);

widget.setWindowFlags(Qt::FramelessWindowHint);

3. 无父窗口,加标志Qt::ToolTip标志,方法同2

4. 无父窗口,加标志Qt::SplashScreen

对于有父窗口,通过加上Qt::Window能不能变成有边框窗口,答案是不行的,那要加边框怎么办,只有自定义了。

接下来我们来看第二个问题,怎么限定窗口的大小?

有时候因为设计的需要,我们往往会限定窗口的大小,QT提供了如下限定窗口尺寸的方法:

/*限定窗口的宽度和高度*/

void setFixedSize(int w, int h)

/*限定窗口的宽度*/

void setFixedWidth(int w)

/*限定窗口的高度*/

void setFixedHeight(int h)

/*限定窗口的最大尺寸,窗口的范围(0, 0)到(w,h)*/

void setMaximumSize (const QSize & size)

void setMaximumSize (int maxw, int maxh)

/*限定窗口的最大高度,高度范围[0,maxh]*/

void setMaximumHeight(int maxh)

/*限定窗口的最大宽度,宽度范围[0, maxw]*/

void setMaximumWidth(int maxw)

/*限定窗口的最小尺寸,窗口的范围>=(w, h)*/

void setMinimumSize (const QSize & size)

void setMinimumSize (int maxw, int maxh)

/*限定窗口的最小高度,高度>=maxh*/

void setMinimumHeight(int maxh)

/*限定窗口的最小宽度,宽度>=maxw*/

void setMinimumWidth(int maxw)

深度探索QT窗口系统——几何篇相关推荐

  1. 深度探索Qt窗口系统——布局篇

    深度探索Qt窗口系统--布局篇 虽然界面管理器可以完成窗口布局,但是对于动态布局的情况下,这种做法就无能为力了,现实中界面经常要支持国际化,对于同一内容用不同语言翻译可能长度不一,这就需要窗口动态布局 ...

  2. 将OSG嵌入QT窗口系统中,实现拖拽界面

    将OSG嵌入QT窗口系统中,实现拖拽界面 一.原理 OSG底层使用的是OpenGL图形系统,QT也增加了对OpenGL的支持,因此,可以通过QT的OpenGL模块,实现将OSG窗口嵌入到QT中,这样可 ...

  3. nubia基于android深度定制的ui,系统硬件篇:走心的Nubia UI

    系统篇:走心的Nubia UI 系统方面,努比亚M2搭载了基于Android深度定制的Nubia UI 4.0系统,同时针对努比亚M2的定位和风格,对系统的界面和图标进行了重新的绘制,这款换上全新风格 ...

  4. 《Android深度探索(卷2):系统应用源代码分析与ROM定制》——第6章,第6.4节分析第一个Android系统应用:计算器...

    本节书摘来自异步社区<Android深度探索(卷2):系统应用源代码分析与ROM定制>一书中的第6章,第6.4节分析第一个Android系统应用:计算器,作者 李宁,更多章节内容可以访问云 ...

  5. [Qt教程] 第47篇 进阶(七) 定制Qt帮助系统

    [Qt教程] 第47篇 进阶(七) 定制Qt帮助系统 楼主  发表于 2013-10-7 09:32:39 | 查看: 93| 回复: 0 定制Qt帮助系统 版权声明 该文章原创于Qter开源社区(w ...

  6. Qt开源库-顶级浮动窗口系统-Advanced-Docking-System【01】

    一.序言 顶级浮动窗口是大型软件中的常备组件,例如Visual Studio Code软件界面: 在上图中,将软件界面划分为不同的功能区,每个功能区负责显示软件的一部分功能.在上图中有项目工程管理窗口 ...

  7. [Qt教程] 第11篇 2D绘图(一)绘制简单图形

    [Qt教程] 第11篇 2D绘图(一)绘制简单图形 楼主  发表于 2013-4-23 12:52:35 | 查看: 1398| 回复: 5 绘制简单图形 版权声明 该文章原创于Qter开源社区,作者 ...

  8. 深度学习论文阅读目标检测篇(四)中英文对照版:YOLOv1《 You Only Look Once: Unified, Real-Time Object Detection》

    深度学习论文阅读目标检测篇(四)中英文对照版:YOLOv1< You Only Look Once: Unified, Real-Time Object Detection> Abstra ...

  9. 深度学习论文阅读目标检测篇(一):R-CNN《Rich feature hierarchies for accurate object detection and semantic...》

    深度学习论文阅读目标检测篇(一):R-CNN<Rich feature hierarchies for accurate object detection and semantic segmen ...

最新文章

  1. 2020技术趋势报告-中文版
  2. 由一次奇怪的编译出错想起的
  3. 建议转变编程时的思维习惯改为:忽略细节关扰,直指问题核心,追寻问题关键。...
  4. JVM学习笔记(一)------基本结构
  5. 文献学习(part30)--Clustering of temporal gene expression data by regularized spline regression and...
  6. CSS中的!important属性用法
  7. 灰度实战(四):Apollo配置中心(4)
  8. 【限时免费】大千万象,“爬”你所需!老司机教你利用爬虫建造一座图书馆...
  9. 电商常用三大数据分析模型--深入浅出
  10. 计算机模拟求解流体力学方程,计算流体力学模拟(CFD模拟)FLUENT中的湍流模型(一)...
  11. cad记忆口诀_CAD的制图口诀
  12. Python 实现端口扫描器
  13. 01 MQTT小例子-连接
  14. win10下卜卦占星工具
  15. 代码中的软件工程:正则表达式十步通关
  16. 数据结构:单链表——带头结点与不带头结点步骤详解
  17. 微信小程序之页面样式以及背景图片显示问题
  18. 美图秀秀开发插件生成的图片都有哪些格式?
  19. unraid虚拟linux系统,UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大!...
  20. 三国志战略版:三势贾的另类搭配,也可以这么强?

热门文章

  1. Linux 命令(83)—— groups 命令
  2. cout输出格式不常用情况
  3. 解决wps如何只复制标题文字(不复制正文)
  4. Spring入门第十七课
  5. Android 相关翻译
  6. 在线CSV转JSON工具
  7. 在线HTML5,CSS3,VueJS,jQuery运行测试练习工具
  8. linux之rsync远程同步文件
  9. [雪峰磁针石博客]数据仓库快速入门教程1简介
  10. 前端单页路由《stateman》源码解析