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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liubing8609/article/details/89423477

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

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

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

1. Qt窗体的几何属性

下图是典型的QT窗口:

https://img-blog.csdn.net/20130526095631138

灰色部分是窗体的边框,白色区域为窗口的内容区域,绿色区域为窗口标题,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();

}

widgetmove(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();

}

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

pos() = QPoint(100,100)

pos() = QPoint(0,0)

https://img-blog.csdn.net/20130526185130971

通过上面的输出结果,我们不难得出结论,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个方面讲了通过resizesetGeometry对窗口缩放的方法,接下来给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();

}

下面是运行结果:

https://img-blog.csdn.net/20130526232947155

https://img-blog.csdn.net/20130526232924072

当单击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)

猜你喜欢

转载自blog.csdn.net/liubing8609/article/details/89423477