这是本人第一篇博客,主要关于QT如何调试的问题
将主函数内容更改如下:
#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
int x = widget.x();
int y = widget.y();
QRect geometry = widget.geometry();
QRect frame = widget.frameGeometry();
return a.exec();
}
x()、y()分别返回部件的位置坐标的x、y值,它们的默认值为0。
而geometry()和frameGeometry()函数分别返回没有边框和包含边框的窗口框架矩形的值,其返回值是QRect类型的,就是一个矩形,它的形式是(位置坐标,大小信息),也就是(x,y,宽,高)。
下面在int x = widget.x(); 一行代码的标号前面点击鼠标左键来设置断点。
所谓断点,就是程序运行到该行代码时会暂停下来,从而可以查看一些信息,如变量值等。要取消断点,只要在那个断点上再点击一下就可以了。设置好断点后便可以按下F5或者左下角的调试按钮开始调试。这时程序会先进行构建再进入调试模式,这个过程可能需要一些时间。在程序构建时可能会出现警告,那是因为我们定义了变量却没有使用造成的,不用管它。
①继续按钮。程序在断点处停了下来,按下继续按钮后,程序便会像正常运行一样,执行后面的代码,直到遇到下一个断点,或者程序结束。
②停止调试按钮。按下该按钮后结束调试。
③单步跳过按钮。直接执行本行代码,然后指向下一行代码。
④单步进入按钮。进入调用的函数内部。
⑤单步跳出按钮。当进入函数内部时,跳出该函数,一般与单步进入配合使用。
⑥重新启动调试会话。
⑦显示源码对应的汇编指令,并可以单步调试。
⑧堆栈视图。这里显示了从程序开始到断点处,所有嵌套调用的函数所在的源文件名和行号。
⑨其它视图。这里可以选择多种视图。
点击一下“单步进入”按钮,或者按下F11,这时,程序会跳转到QWidget类的x()函数的源码处,这里对这个函数不做过多讲解,下面直接按下“单步跳出”按钮回到原来的断点处。然后便开始一直按“单步跳过”按钮,单步执行程序,并查看局部变量和监视器视图中相应变量值的变化情况。等执行到最后一行代码return a.exec();时,按下“停止调试”按钮,结束调试。
这里要补充说明一下,我们在程序调试过程中可以进入到Qt类的源码中,其实还有一个很简单的方法也可以实现这个功能,就是在编辑器中将鼠标光标定位到一个类名或者函数上,然后按下F2键,或者点击鼠标右键,选择“跟踪光标位置的符号”,这时编辑器就会跳转到其源码处。
从变量监视器中可以看到x、y、geometry和frame四个变量初始值都是一个随机未知数。等到调试完成后,x、y的值均为0,这是它们的默认值。而geometry的值为640x480+0+0,frame的值为639x479+0+0。
现在对这些值还不是很清楚,不过,为什么x、y的值会是0呢?我们可能会想到,应该是窗口没有显示的原因,那么就更改代码,让窗口先显示出来,再看这些值。在QWidget widget;一行代码后添加一行代码:
widget.show();
现在再次调试程序,这时会发现窗口只显示了一个标题栏,先不管它,继续在Qt Creator中点击“单步跳过”按钮。当我们将程序运行到最后一行代码return a.exec();时,再次按下“单步跳过”按钮后,程序窗口终于显示出来了。这是因为只有程序进入主事件循环后才能接收事件,而show()函数会触发显示事件,所以只有在完成a.exe()函数调用进入消息循环后才能正常显示。这次看到几个变量的值都有了变化,但是这时还是不清楚这些值的含义。
注意:因为使用调试器进行调试要等待一段时间,而且步骤很麻烦,对于初学者来说,如果按错了按钮,还很容易出错。 所以,并不推荐初学者使用。
一般在程序调试过程中很常用的是qDebug()函数,它可以将调试信息直接输出到控制台,在Qt Creator中是输出到应用程序输出栏 。例如:
QWidget widget;
widget.resize(400, 300); // 设置窗口大小
widget.move(200, 100); // 设置窗口位置
widget.show();
int x = widget.x();
qDebug("x: %d", x); // 输出x的值
int y = widget.y();
qDebug("y: %d", y);
QRect geometry = widget.geometry();
QRect frame = widget.frameGeometry();
qDebug() << "geometry: " << geometry << "frame: " << frame;
要使用qDebug()函数,就要添加#include 头文件。然后这里使用了两种输出方式:
方式一:直接将字符串当做参数传给qDebug()函数,例如上面使用这种方法输出x和y的值。
方式二:使用输出流的方式一次输出多个值,它们的类型可以不同,例如程序中输出geometry和frame的值。
需要说明的是,如果只使用第一种方法,那么是不需要添加头文件的,如果使用第二种方法就必须添加这个头文件。因为第一种方法很麻烦,所以经常使用的是第二种方法。
其实使用qDebug()函数的第二种方法时还可以让输出自动换行,下面来看一下其他几个函数的用法。在return a.exec();一行代码前添加如下代码:
qDebug() << “pos:” << widget.pos() << endl << “rect:” << widget.rect()
<< endl << “size:” << widget.size() << endl << “width:”
<< widget.width() << endl<< “height:” << widget.height();
这里的“endl”就是起换行作用的。
根据程序的输出结果,可以很明了的看到这些函数的作用。
其中pos()函数返回窗口的位置,是一个坐标值,上面的x()、y()函数返回的就是它的x、y坐标值;
rect()函数返回不包含边框的窗口内部矩形,在窗口内部,左上角是(0,0)点;
size()函数返回不包含边框的窗口大小信息;
width()和height()函数分别返回窗口内部的宽和高。
从数据可以看到,前面使用的调整窗口大小的resize()函数是设置的不包含边框的窗口大小。