用QT建立的第一个工程

摘要:本文主要是利用向导创建了第一个qt工程文件,主要介绍了工程文件的结构、main函数、按钮的创建、qt中的对象树、坐标系、qt中的信号和槽等概念。

一、工程文件的结构

利用qt导向创建好工程文件之后,会自动生成main函数、头文件、源文件和Pro文件,以下图:数组

二、main函数

在这个main函数中,主要建立了一个窗口对象w,调用构造函数,实现一些按钮、信号和槽的功能。函数

 1 #include "mywidget.h" //包含头文件
 2 #include <QApplication> //包含QApplication头文件  3 
 4 //程序入口 argc命令行变量的数量 argv命令行变量数组
 5 int main(int argc, char *argv[])  6 {  7     QApplication a(argc, argv); //a 应用程序对象,对于Qt项目必须有应用程序对象,并且有且仅有一个
 8     MyWidget w; //建立一个MyWidget对象
 9     w.show(); //建立出的窗口对象并不会直接显示,须要调用show方法
10 
11     return a.exec(); //进入消息循环机制,阻塞状态 12 // while(true) 13 // { 14 // if(点击叉子) 15 // break; 16 // }
17 }

三、myweiget.cpp和myweiget.h

在头文件中,重点注意类中加了“Q_OBJECT”,构造函数有默认参数。工具

 1 #ifndef MYWIDGET_H  2 #define MYWIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 //继承于QWidget
 7 class MyWidget : public QWidget  8 {  9     //支持Qt中的信号和槽使用
10  Q_OBJECT 11 
12 public: 13     MyWidget(QWidget *parent = 0); //构造
14     ~MyWidget(); //析构
15 }; 16 
17 #endif // MYWIDGET_H

在源文件中,注意函数变量的名字两个单词之间用大写字母隔开;注意建立按钮的两种方法;为按钮添加文本,设置按钮位置,设置按钮大小;重置窗口的大小和窗口名称等方法。重点是学会查看帮助文档。测试

 1 #include "mywidget.h"
 2 #include<QPushButton>
 3 #include "mybutton.h"
 4 #include <QDebug>
 5 
 6 MyWidget::MyWidget(QWidget *parent)  7  : QWidget(parent)  8 {  9     QPushButton * btn =new QPushButton; 10 
11     // btn->show(); 12     //btn应该依赖于主窗口
13     btn->setParent(this); 14     //显示文字
15     btn->setText("德玛"); 16 
17     //第二种建立方式
18     QPushButton * btn2 = new QPushButton("德玛西亚",this); 19     //移动窗口
20     btn2->move(100,100); 21     //重置窗口大小
22     resize(960,640); 23 
24     //btn可不能够 resize? 能够
25     btn2->resize(50,50); 26 
27     //设置窗口标题名称
28     this->setWindowTitle("德玛西亚万岁"); 29 
30     //对象树
31     MyButton * myBtn = new MyButton(); 32     myBtn->setParent(this); 33     myBtn->move(200,200); 34     myBtn->setText("个人按钮"); 35 
36     //窗体的坐标系 37     //左上角为 0 0 点 38     // x 以右侧为正方向 y 如下侧为正方向 39 
40     //需求 点击“个人按钮” ,关闭窗口 41     //链接信号槽的关键字 connect 42     //4个参数 参数1 信号发送者 参数2 发送的信号 参数3 信号的接受者 参数4 处理的槽函数 43     //参数2 和参数4 须要的都是函数地址
44 
45     connect(myBtn,&QPushButton::clicked,this,&MyWidget::close); 46 
47 } 48 
49 MyWidget::~MyWidget() 50 { 51     qDebug("MyWidget析构了!"); 52 }

四、对象树

先来看一幅图:ui

(1)在qt中,QObject是以对象树的形式组织起来的。

  •  当你建立一个QObject对象时,会看到QObject的构造函数接收一个QObject指针做为参数,这个参数就是 parent,也就是父对象指针。这至关于,在建立QObject对象时,能够提供一个其父对象,咱们建立的这个QObject对象会自动添加到其父对象的children()列表例如上面的3中的构造函数MyWidget::MyWidget(QWidget *parent): QWidget(parent)
  • 当父对象析构的时候,这个列表中的全部对象也会被析构。(注意,这里的父对象并非继承意义上的父类!)这种机制在 GUI 程序设计中至关有用。例如,一个按钮有一个QShortcut(快捷键)对象做为其子对象。当咱们删除按钮的时候,这个快捷键理应被删除。这是合理的。

(2)QWidget是可以在屏幕上显示的一切组件的父类。

  • QWidget继承自QObject,所以也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。所以,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,咱们但愿属于这个对话框的按钮、图标等应该一块儿被删除。事实就是如此,由于这些都是对话框的子组件。
  • 固然,咱们也能够本身删除子对象,它们会自动从其父对象列表中删除好比,当咱们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,而且自动调整屏幕显示。
  • Qt 引入对象树的概念,在必定程度上解决了内存问题。

(3)当一个QObject对象在堆上建立的时候,Qt 会同时为其建立一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。

(4)任何对象树中的 QObject对象 delete 的时候,若是这个对象有 parent,则自动将其从 parent 的children()列表中删除;若是有孩子,则自动 delete 每个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

(5)注意的问题:

若是QObject在栈上建立,Qt 保持一样的行为。正常状况下,这也不会发生什么问题。来看下下面的代码片断:this

1 { 2  QWidget window; 3     QPushButton quit("Quit", &window); 4 }

做为父组件的 window 和做为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,由于标准 C++要求,局部对象的析构顺序应该按照其建立顺序的相反过程。所以,这段代码在超出做用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,而后才会再调用 window 的析构函数。spa

可是,若是咱们使用下面的代码:命令行

1 { 2     QPushButton quit("Quit"); 3  QWidget window; 4     quit.setParent(&window); 5 }

状况又有所不一样,析构顺序就有了问题。咱们看到,在上面的代码中,做为父对象的 window 会首先被析构,由于它是最后一个建立的对象。在析构过程当中,它会调用子对象列表中每个对象的析构函数,也就是说, quit 此时就被析构了。而后,代码继续执行,在 window 析构以后,quit 也会被析构,由于 quit 也是一个局部变量,在超出做用域的时候固然也须要析构。可是,这时候已是第二次调用 quit 的析构函数了,C++ 不容许调用两次析构函数,所以,程序崩溃了。设计

由此咱们看到,Qt 的对象树机制虽然帮助咱们在必定程度上解决了内存问题,可是也引入了一些值得注意的事情。这些细节在从此的开发过程当中极可能时不时跳出来烦扰一下,因此,咱们最好从开始就养成良好习惯,在 Qt 中,尽可能在构造的时候就指定 parent 对象,而且大胆在堆上建立。指针

(6)总结:

  • 全部new出来的对象 不用管释放
  • 缘由 children表中的对象会在窗口关闭后进行自动释放

(7)测试代码

mybutton.h

 1 #ifndef MYBUTTON_H  2 #define MYBUTTON_H
 3 
 4 #include <QWidget>
 5 #include <QPushButton>
 6 
 7 class MyButton : public QPushButton  8 {  9  Q_OBJECT 10 public: 11     explicit MyButton(QWidget *parent = 0); 12     ~MyButton(); 13 signals: 14 
15 public slots: 16 }; 17 
18 #endif // MYBUTTON_H

mybutton.cpp

 1 #include "mybutton.h"
 2 #include <QDebug>
 3 MyButton::MyButton(QWidget *parent) : QPushButton(parent)  4 {  5 
 6 }  7 
 8 MyButton::~MyButton()  9 { 10     qDebug() << "MyButton调用析构了!"; 11 
12 }

上面代码的执行结果是:

MyWidget析构了!

MyButton调用析构了!

这样的析构顺序和我咱们想象的不太一致,咱们会认为是先析构按钮再析构窗口,然而显示的结果却不是这样的。实际上咱们的想法是正确的,这是由于在执行到窗口析构的过程当中,会出现按钮的析构,等按钮析构完成之后,再返回窗口析构。

五、窗口的坐标系

原点在左上角

六、信号槽的基本使用

具体的使用见代码

相关文章
相关标签/搜索