《QtCreator快速入门》第2版第3章窗口部件(1课时)前一章中第一次建立helloworld程序时,曾看到QtCreator提供的默认基类只有QMainWindow、QWidget和QDialog三种。是的,这三种窗体也是以后用的最多的,QMainWindow是带有菜单栏和工具栏的主窗口类,QDialog是各种对话框的基类,而它们二者全部继承自QWidget。不仅如此,其实所有的窗口部件都继承自QWidget。主要内容3.1基础窗口部件QWidget3.2对话框QDialog3.3其他窗口部件3.4小结3.1基础窗口部件QWidgetQWidget类是所有用户界面对象的基类,被称为基础窗口部件。QWidget继承自QObject类和QPaintDevice类,其中QObject类是所有支持Qt对象模型(QtObjectModel)的Qt对象的的基类,QPaintDevice类是所有可以绘制的对象的基类。本节内容:窗口、子部件以及窗口类型窗口几何布局程序调试窗口、子部件以及窗口类型来看一个代码片段://新建QWidget类对象,默认parent参数是0,所以它是个窗口QWidget*widget=newQWidget();//设置窗口标题widget-setWindowTitle(QObject::tr(我是widget));//新建QLabel对象,默认parent参数是0,所以它是个窗口QLabel*label=newQLabel();label-setWindowTitle(QObject::tr(我是label));//设置要显示的信息label-setText(QObject::tr(label:我是个窗口));//改变部件大小,以便能显示出完整的内容label-resize(180,20);//label2指定了父窗口为widget,所以不是窗口QLabel*label2=newQLabel(widget);label2-setText(QObject::tr(label2:我不是独立窗口,只是widget的子部件));label2-resize(250,20);//在屏幕上显示出来label-show();widget-show();在程序中定义了一个QWidget类对象的指针widget和两个QLabel对象指针label与label2,其中label没有父窗口,而label2在widget中,widget是其父窗口。窗口部件(Widget)这里简称部件,是Qt中建立用户界面的主要元素。像主窗口、对话框、标签、还有以后要介绍到的按钮、文本输入框等都是窗口部件。在Qt中,把没有嵌入到其他部件中的部件称为窗口,一般的,窗口都有边框和标题栏,就像程序中的widget和label一样。QMainWindow和大量的QDialog子类是最一般的窗口类型。窗口就是没有父部件的部件,所以又称为顶级部件(top-levelwidget)。与其相对的是非窗口部件,又称为子部件(childwidget)。在Qt中大部分部件被用作子部件,它们嵌入在别的窗口中,例如程序中的label2。窗口类型前面讲到窗口一般都有边框和标题栏,其实这也不是必需的:QWidget的构造函数有两个参数:QWidget*parent=0和Qt::WindowFlagsf=0;前面的parent就是指父窗口部件,默认值为0,表明没有父窗口;而后面的f参数是Qt::WindowFlags类型的,它是一个枚举类型,分为窗口类型(WindowType)和窗口标志(WindowFlags。前者可以定义窗口的类型,比如我们这里f=0,表明使用了Qt::Widget一项,这是QWidget的默认类型,这种类型的部件如果有父窗口,那么它就是子部件,否则就是独立的窗口。例如:使用其中的Qt::Dialog和Qt::SplashScreen,更改程序中的新建对象的那两行代码:QWidget*widget=newQWidget(0,Qt::Dialog);QLabel*label=newQLabel(0,Qt::SplashScreen);当更改窗口类型后,窗口的样式发生了改变,一个是对话框类型,一个是欢迎窗口类型。而对于窗口标志,它主要的作用是更改窗口的标题栏和边框,而且它们可以和窗口类型进行位或操作。下面再次更改那两行代码:QWidget*widget=newQWidget(0,Qt::Dialog|Qt::FramelessWindowHint);QLabel*label=newQLabel(0,Qt::SplashScreen|Qt::WindowStaysOnTopHint);Qt::FramelessWindowHint用来产生一个没有边框的窗口,而Qt::WindowStaysOnTopHint用来使该窗口停留在所有其它窗口上面。窗口几何布局对于窗口的大小和位置,根据是否包含边框和标题栏两种情况,要用不同的函数来获取它们的数值。这里的函数分为两类,一类是包含框架的,一类是不包含框架的:包含框架:x()、y()、frameGeometry()、pos()和move()等函数;不包含框架:geometry()、width()、height()、rect()和size()等函数。程序调试下面在讲解窗口几何布局的几个函数的同时,讲解一下程序调试方面的内容。将主函数内容更改如下:#includeQApplication#includeQWidgetintmain(intargc,char*argv[]){QApplicationa(argc,argv);QWidgetwidget;intx=widget.x();inty=widget.y();QRectgeometry=widget.geometry();QRectframe=widget.frameGeometry();returna.exec();}x()、y()分别返回部件的位置坐标的x、y值,它们的默认值为0。而geometry()和frameGeometry()函数分别返回没有边框和包含边框的窗口框架矩形的值,其返回值是QRect类型的,就是一个矩形,它的形式是(位置坐标,大小信息),也就是(x,y,宽,高)。下面在intx=widget.x();一行代码的标号前面点击鼠标左键来设置断点。所谓断点,就是程序运行到该行代码时会暂停下来,从而可以查看一些信息,如变量值等。要取消断点,只要在那个断点上再点击一下就可以了。设置好断点后便可以按下F5或者左下角的调试按钮开始调试。这时程序会先进行构建再进入调试模式,这个过程可能需要一些时间。在程序构建时可能会出现警告,那是因为我们定义了变量却没有使用造成的,不用管它。调试模式下面对调试模式的几个按钮和窗口进行简单介绍:①继续按钮。程序在断点处停了下来,按下继续按钮后,程序便会像正常运行一样,执行后面的代码,直到遇到下一个断点,或者程序结束。②停止调试按钮。按下该按钮后结束调试。③单步跳过按钮。直接执行本行代码,然后指向下一行代码。④单步进入按钮。进入调用的函数内部。⑤单步跳出按钮。当进入函数内部时,跳出该函数,一般与单步进入配合使用。⑥显示源码对应的汇编指令,并可以单步调试。⑦堆栈视图。这里显示了从程序开始到断点处,所有嵌套调用的函数所在的源文件名和行号。⑧其它视图。这里有局部变量和监视器视图,用来显示局部变量和它们的类型及数值;断点视图用来显示所有的断点,以及添加或者删除断点;线程视图用来显示所有的线程和现在所在的线程;快照视图用来管理快照,快照可以保存当前的调试状态。单步调试点击一下“单步进入”按钮,或者按下F11,这时,程序会跳转到QWidget类的x()函数的源码处,这里对这个函数不做过多讲解,下面直接按下“单步跳出”按钮回到原来的断点处。然后便开始一直按“单步跳过”按钮,单步执行程序,并查看局部变量和监视器视图中相应变量值的变化情况。等执行到最后一行代码returna.exec();时,按下“停止调试”按钮,结束调试。这里要补充说明一下,我们在程序调试过程中可以进入到Qt类的源码中,其实还有一个很简单的方法也可以实现这个功能,就是在编辑器中将鼠标光标定位到一个类名或者函数上,然后按下F2键,或者点击鼠标右键,选择“跟踪光标位置的符号”,这时编辑器就会跳转到其源码处。从变量监视器中可以看到x、y、geometry和frame四个变量初始值都是一个随机未知数。等到调试完成后,x、y的值均为0,这是它们的默认值。而geometry的值为640x480+0+0,frame的值为639x479+0+0。现在对这些值还不是很清楚,不过,为什么x、y的值会是0呢?我们可能会想到,应该是窗口没有显示的原因,那么就更改代码,让窗口先显示出来,再看这些值。在QWidgetwidget;一行代码后添加一行代码:widget.show();现在再次调试程序,这时会发现窗口只显示了一个标题栏,先不管它,继续在QtCreator中点击“单步跳过”按钮。当我们将程序运行到最后一行代码returna.exec();时,再次按下“单步跳过”按钮后,程序窗口终于显示出来了。这是因为只有程序进入主事件循环后才能接收事件,而show()函数会触发显示事件,所以只有在完成a.exe()函数调用进入消息循环后才能正常显示。这次看到几个变量的值都有了变化,但是这时还是不清楚这些值的含义。注意:因为使用调试器进行调试要等待一段时间,而且步骤很麻烦,对于初学者来说,如果按错了按钮,还很容易出错。所以,并不推荐使用。使用qDebug()函数一般在程序调试过程中很常用的是qDebug()函数,它可以将调试信息直接输出到控制台,在QtCreator中是输出到应用程序输出栏。例如:QWidgetwidget;widget.resize(400,300);//设置窗口大小widget.move(200,100);//设置窗口位置widget.show();intx=widget.x();qDebug(x:%d,x);//输出x的值inty=widget.y();qDebug(y:%d,y);QRectgeometry=widget.geometry();QRectframe=widget.frameGeometry();qDebug()geometry:geometryframe:frame;要使用qDebug()函数,就要添加#includeQDebug头文件。然后这里使用了两种输出方式:方式一:直接将字符串当做参数传给qDebug()函数,例如上面使用这种方法输出x和y的值。方式二:使用输出流的方式一次输出多个值,它们的类型可以不同,例如程序中输出geometry和frame的值。需要说明的是,如果只使用第一种方法,那么是不需要添加QDebug头文件的,如果使用第二种方法就必须添加这个头文件。因为第一种方法很麻烦,所以经常使用的是第二种方法。从输出信息中,可以清楚的看到几个函数的含义了。其实使用qDebug()函数的第二种方法时还可以让输出自动换行,下面来看一下其他几个函数的用法。在returna.exec();一行代码前添加如下代码:qDebug()pos:widget.pos()endlrect:widget.rect()endlsize:widget.size()endlwidth:widget.width()endlheight:widget.height();这里的“endl”就是起换行作用的。根据程序的输出结果,可以很明了的看到这些函数的作用。其中pos()函数返回窗口的位置,是一个坐标值,上面的x()、y()函数返回的就是它的x、y坐标值;rect()函数返回不包含边框的窗口内部矩形,在窗口内部,左上角是(0,0)点;