QWidget和QMainWindow是QWidget的子类。
如果是主窗口,就使用QMainWindow.
如果是对话框,就使用QDialog.
如果不确定,既可能作为顶级窗口,也可能嵌入到其他窗口,则使用QWidget.
注:窗口和控件都继承自QWidget,若不为控件指定父对象,他就会被作为窗口处理,这时setWindowTitle() 【设置窗口标题】和 setWindowIcon() 函数【设置窗口图标】就会生效。
#include "mywidget.h"
#include //包含一个应用程序类的头文件
//main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //a应用程序对象,在Qt中,应用对象程序有且仅有一个
myWidget w; //窗口对象 myWidget父类 -> QWidget
w.show(); //窗口对象默认不会显示,必须调用show方法显示窗口
return a.exec(); //让程序进入消息循环机制
}
工程文件(project),qmake自动生成,用于makefile的配置文件
QT += core gui //Qt包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于4版本 包含widget模块
TARGET = first //目标 生成.exe程序的名称
TEMPLATE = app //模板 应用程序模板 Application
/*
app -建立一个应用程序的makefile。这是默认值,所以如果模板没有被指被使用。
lib - 建立一个库的makefile。
vcapp - 建立一个应用程序的VisualStudio项目文件。
vclib - 建立一个库的VisualStudio项目文件。
subdirs -这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成makefile并且为它调用make的makefile。
*/
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
/*CONFIG用来告诉qmake关于应用程序的配置信息。*/
CONFIG += c++11
/*使用c++11的特性,在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那样替换已经指定的所有选项更安全。*/
SOURCES += \ //源文件
main.cpp \
mywidget.cpp
HEADERS += \ //头文件
mywidget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include //包含头文件QWidget 窗口类
class myWidget : public QWidget
{
Q_OBJECT宏,允许类中使用信号和槽的机制 // Q_OBJECT宏,允许类中使用信号和槽的机制
public:
myWidget(QWidget *parent = 0); //构造函数
~myWidget(); //析构函数
};
#endif // MYWIDGET_H
注释 ctrl +/
运行 ctrl + r
编译 ctrl + b
字体缩放 ctrl +鼠标滚轮
查找 ctrl + f
整行移动 ctrl +shift +↑或者↓
帮助文档 F1 或 文件目录(我的:E:\qt\5.12.0\mingw73_64\bin)
自动对齐 ctrl+i
同名.h和.cpp文件切换 F4
在Qt中创建对象的时候会提供一个Parent对象指针
QObject是以对象树的形式组织起来的。
n 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。
这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
n 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
当创建的对象在堆区时,如果指定的父亲是QObject派生下来的类或QObject子类派生下来的类,可以不用管理释放的操作,将对象放回到对象树中。
一定程度上简化了内存回收机制
在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。
lQObject是以对象树的形式组织起来的。
当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
n 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
QWidget是能够在屏幕上显示的一切组件的父类。
QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
当然,**我们也可以自己删除子对象,它们会自动从其父对象列表中删除。**比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。
Qt 引入对象树的概念,在一定程度上解决了内存问题。
当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
l 任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。
如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。
来看下下面的代码片段:
{
QWidget window;
QPushButton button = QPushButton ("退出", &window);
}
作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。
但是,如果我们使用下面的代码:
{
QPushButton quit("Quit");
QWidget window;
quit.setParent(&window);
}
情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。
由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯。
在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。
左上角为原点,X向右增加,Y向下增加
connect()函数最常用的一般形式:
connect(sender, signal, receiver, slot);
参数解释:
sender:发出信号的对象
signal:发送对象发出的信号
receiver:接收信号的对象
slot:接收对象在接收到信号之后所需要调用的函数(槽函数)