QT基础知识总结.docx
《QT基础知识总结.docx》由会员分享,可在线阅读,更多相关《QT基础知识总结.docx(17页珍藏版)》请在冰点文库上搜索。
QT基础知识总结
0.Tips
字体颜色
蓝色:
绿色:
头文件和注释
浅黄:
数据类型和keyword
紫色:
类名(注意不是对象名)
青色:
函数名,若倾斜字体则还表示父类中也有同名函数?
1.新建项目
选择“QtWidgetsApplication”。
项目名称:
Test。
Kitselection:
只选择“DesktopQt5.12.0MinGW64-bit”。
再然后就是“类信息”对话框,基类有三种(详细内容参见网址),此处选择默认的QMainWindow。
然后将“创建界面”取消掉,不产生界面文件“mainwindow.ui”,然后完成项目的创建。
2.项目文件理解
项目有四个文件,如上图所示。
pro文件是QT工程文件(projectfile);main.cpp里面就是一个main函数,作为应用程序的入口函数。
另两个文件mainwindow.h和mainwindow.cpp就是我们在创建项目过程中“类信息”对话框时所指定的头文件和源文件。
(1)main.cpp文件
前两行include语句引入的是MainWindow和QApplication这两个类。
代码第4行。
main函数的两个形参argc和argv分别代表argumentcounter和argumentvalues,因此argc记录了输入参数的个数,argv[]是记录字符串数组的,字符串数组的每个单元是char*类型的,指向一个c风格字符串。
代码第6行。
main函数首先创建一个QApplication类的对象,后面才是实际业务的代码。
QApplication类管理图形用户界面应用程序的控制流和主要设置。
QApplication对象做了很多初始化,它必须在所有与用户界面相关的其它类被创建之前被创建。
(详情参见网址)
代码第7-8行。
在我们创建了QApplication对象之后,创建了一个MainWindow类的对象w,该对象又调用了成员函数show()显示出来。
代码最后一行,a.exec,进入主事件循环并且等待,直到exit()被调用或者主窗口部件被销毁,并且返回值被设置为exit()。
exec()函数的真正含义是开启一个新的事件循环。
所谓事件循环,可以理解成一个无限循环。
Qt在开启了事件循环之后,系统发出的各种事件才能够被程序监听到。
这个事件循环相当于一种轮询的作用。
既然是无限循环,当然在开启了事件循环的地方,代码就会被阻塞,后面的语句也就不会被执行到。
(2)mainwindow.h
类声明。
代码第1、2和15行。
关于#ifndef/define/endif,可以下面这张图可以理解,注意ifndef和ifdef的区别。
代码第4行。
#include,因MainWindow类继承自QMainWindow基类。
详细继承关系为:
MainWindow—QMainWindow—QWidget—QObject。
QObject类是所有Qt对象的基类。
QObject是Qt对象模型的中心。
这个模型的中心特征就是一种用于无缝对象通讯的被叫做信号和槽的非常强大的机制。
代码第8行。
在类声明里头还有个宏“Q_OBJECT”。
凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。
不管是不是使用信号槽,都应该添加这个宏。
这个宏的展开将为我们的类提供信号槽机制、国际化机制以及Qt提供的不基于C++RTTI的反射能力。
代码第11行。
构造函数,在
代码第12行。
析构函数。
(3)mainwindow.cpp
类定义。
代码第1行。
头文件的作用。
代码第3-6行。
构造函数的定义。
构造一个空的主窗口,parent被传递给QWidget构造函数。
代码第8-11行。
析构函数的定义。
(4)其他
修改主窗口标题,可在w.show前加一句代码:
w.setWindowTitle(“HelloWorld!
”);注意setWindowTitle是类QWidget的公有成员函数。
3.信号槽机制
3.1按钮为例
以按钮为例进行说明。
代码第2行。
需创建QPushButton类对象,所以要包含相应的头文件。
QPushButton继承自QButton,QButton继承自QWidget。
代码第8行。
创建QPushButton类对象button。
根据QPushButton类构造函数的定义,可指定按钮文本,如代码所示。
代码第9行。
因QPushButton同样继承自QWidget,所以可以调用setWindowTitle来更改窗口标题。
代码第10行,信号槽机制。
QObject:
:
connect()有五个重载,详细情况可看QT5.12QObject:
:
connect()函数定义。
此类型属于第四种。
五个重载函数声明如下:
此处仅讨论第一、三和四种。
第一种:
Returnsahandletotheconnectionthatcanbeusedtodisconnectitlater.(此处不必关心)sender类型是constQObject*,signal的类型是constchar*,receiver类型是constQObject*,slot类型是constchar*。
这个函数将signal和slot作为字符串处理,必须在说明signal和method(slot)的时候使用SIGNAL()和SLOT()两个宏。
connect函数用到的SIGNAL()和SLOT()这两个宏,其实就是分别生成Signal函数字符串和Slot函数字符串。
字符串里包含了函数类型(用SIGNAL()函数类型就是2,用SLOT()函数类型就是1)。
比如:
再看例子:
因此下面的三个connect函数分别表示一回事,都是正确的。
connect()一般会使用前面四个参数,第一个是发出信号的对象,第二个是发送对象发出的信号,第三个是接收信号的对象,第四个是接收对象在接收到信号之后所需要调用的函数。
也就是说,当sender发出了signal信号之后,会自动调用receiver的slot函数。
connect()函数,sender和receiver没有什么区别,都是QObject指针,主要是signal和slot形式的区别。
Notethatthesignalandslotsparametersmustnotcontainanyvariablenames,onlythetype.E.g.thefollowingwouldnotworkandreturnfalse:
将一开始例子中的connect代码替换一下,同样可行。
clicked()是button的成员函数,quit()是a的成员函数。
第三种:
PointerToMemeberFunction函数指针。
需将函数地址取出来,所以用了一个&。
关于细节,有待深究。
第四种:
最后一个参数是Functor类型,可以接受static函数(如staticslot:
voidQCoreApplication:
quit())、全局函数。
信号与槽使用步骤:
Ø发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数等无需接收者的时候除外);
Ø使用signals标记信号函数,信号是一个函数声明,返回void,不需要实现函数代码;
Ø槽函数是普通的成员函数,作为成员函数,会受到public、private、protected的影响;
Ø使用emit在恰当的位置发送信号;
Ø使用QObject:
:
connect()函数连接信号和槽。
信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。
这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。
3.2查看信号来源
qobject_cast<类型*>(sender());//函数定义暂时没看懂
作用是当我们同时有很多信号链接到一个槽中时,当信号发生时,能查看是哪一个对象发出的信号。
A*btn=qobject_cast(sender());
这样我们就能查看是A类的哪一个对象发出了信号。
实际应用:
4.QMainWindow
QMainWindow类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。
通常我们的程序主窗口会继承自QMainWindow,以便获得QMainWindow提供的各种便利的函数。
参考PDF手册
5.资源文件
Qt资源系统是一个跨平台的资源机制,用于将程序运行时所需要的资源以二进制的形式存储于可执行文件内部。
如果你的程序需要加载特定的资源(图标、文本翻译等),那么,将其放置在资源文件中,就再也不需要担心这些文件的丢失。
也就是说,如果你将资源以资源文件形式存储,它是会编译到可执行文件内部。
参考PDF手册
6.QAction
本节,我们将在前面主窗口基础之上,添加菜单和工具栏等的动作。
虽然QtCreator已经帮我们实现了主窗口的框架代码,但是具体的功能,还是需要我们一行行添加。
Qt使用QAction类作为动作。
顾名思义,这个类就是代表了窗口的一个“动作”,这个动作可能显示在菜单,作为一个菜单项,当用户点击该菜单项,对用户的点击做出响应;也可能在工具栏,作为一个工具栏按钮,用户点击这个按钮就可以执行相应的操作。
有一点值得注意:
无论是出现在菜单栏还是工具栏,用户选择之后,所执行的动作应该都是一样的。
因此,Qt并没有专门的菜单项类,只是使用一个QAction类,抽象出公共的动作。
当我们把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。
用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。
QAction包含了图标、菜单文字、快捷键、状态栏文字、浮动帮助等信息。
当把一个QAction对象添加到程序中时,Qt自己选择使用哪个属性来显示,无需我们关心。
同时,Qt能够保证把QAction对象添加到不同的菜单、工具栏时,显示内容是同步的。
也就是说,如果我们在菜单中修改了QAction的图标,那么在工具栏上面这个QAction所对应的按钮的图标也会同步修改。
(QAction类提供了一个可以同时出现在菜单和工具条上的抽象用户界面操作。
QAction可以包含图标、菜单文本、快捷键、状态条文本和工具提示。
它们可以分别通过setIconSet()、setText()、setMenuText()、setToolTip()、setStatusTip()、setWhatsThis()和setAccel()来设置。
)
下图是个QAction类对象的例子,注意在类声明中要声明QActionopenAction类成员变量。
7.菜单栏、工具栏和状态栏
7.1菜单栏
QT中要建立菜单,有三个类很重要:
QMenuBar、QMenu和QAction。
QMenuBar:
就是所有窗口的菜单栏,在此基础上添加不同的QMenu和QAction。
QMenu:
菜单栏里面菜单,可以显示文本和图标,但是并不负责执行操作,有点类似label的作用。
QAction:
Qt将用户与界面进行交互的元素抽象为一种“动作”,使用QAction类表示。
QAction才是真正负责执行操作的部件。
被注释的两行与未被注释的三行,是一回事。
参考PDF手册。
使用menuBar()函数,Qt为我们创建了一个菜单栏。
menuBar()是QMainWindow提供的函数,因此你是不会在QWidget或者QDialog中找到它的。
这个函数会返回窗口的菜单栏,如果没有菜单栏则会新创建一个。
这也就解释了,为什么我们可以直接使用menuBar()函数的返回值。
7.2工具栏
7.3状态栏
我们添加了一个孤零零的statuBar()显得不伦不类,但是,同前面的menuBar()的实现类似,这个函数会返回一个QStatusBar对象,如果没有则先创建再返回。
8.QFileDialog文件对话框
TheQFileDialogclassprovidesadialogthatallowuserstoselectfilesordirectories.
TheQFileDialogclassenablesausertotraversethefilesysteminordertoselectoneormanyfilesoradirectory.
TheeasiestwaytocreateaQFileDialogistousethestaticfunctions.OnWindows,MacOSX,KDEandGNOME,thesestaticfunctionswillcallthenativefiledialogwhenpossible.
Intheaboveexample,amodalQFileDialogiscreatedusingastaticfunction.Thedialoginitiallydisplaysthecontentsofthe"/home/jana"directory,anddisplaysfilesmatchingthepatternsgiveninthestring"ImageFiles(*.png*.jpg*.bmp)".Theparentofthefiledialogissettothis,andthewindowtitleissetto"OpenImage".
另外的解释:
QStringQFileDialog:
:
getOpenFileName(
QWidget*parent=0,
const QString&caption=QString(),
const QString&dir=QString(),
const QString&filter=QString(),
QString*selectedFilter=0,
Optionsoptions=0)
第一个参数parent,用于指定父组件。
注意,很多Qt组件的构造函数都会有这么一个parent参数,并提供一个默认值NULL;
第二个参数caption,是对话框的标题;
第三个参数dir,是对话框显示时默认打开的目录,"."代表程序运行目录,"/"代表当前盘符的根目录(Windows,Linux下/就是根目录了),也可以是平台相关的,比如"C:
\“等;例如我想打开程序运行目录下的Data文件夹作为默认打开路径,这里应该写成”./Data/",若想有一个默认选中的文件,则在目录后添加文件名即可:
"./Data/teaser.graph"
第四个参数filter,是对话框的后缀名过滤器,比如我们使用"ImageFiles(.jpg.png)“就让它只能显示后缀名是jpg或者png的文件。
如果需要使用多个过滤器,使用“;;”分割,比如"JPEGFiles(.jpg);;PNGFiles(.png)";
第五个参数selectedFilter,是默认选择的过滤器;
第六个参数options,是对话框的一些参数设定,比如只显示文件夹等等,它的取值是enumQFileDialog:
:
Option,每个选项可以使用|运算组合起来。
如果需要选择多个文件,Qt提供了getOpenFileNames()函数,其返回值是一个QStringList。
QStringList是存放QString的一个容器,存储多个文件路径。
9.事件
QT中有很多事件:
鼠标事件、键盘事大小改变事件、位置移动事件等等。
每一种事件对应一个事件处理函数。
9.1HowEventsareDelivered
以QWidget为例,其所有的ProtectedVirtualFunctions均是特定事件处理回调函数,例如QWidget:
:
mouseMoveEvent()和Qwidget:
:
mousePressEvent。
Qt程序需要在main()函数创建一个QApplication(orQCoreApplication)对象,然后调用exec()函数。
exec()函数就是开始Qt的事件循环。
在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。
当事件发生时,Qt将创建一个事件对象。
Qt中所有事件类都继承于QEvent。
在事件对象创建完毕后,Qt将这个事件对象传递给QWidget的event()函数。
event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(eventhandler),如mouseMoveEvent()/mousePressEvent()。
由于所有的事件处理函数都是protectedvirtual的,因此我们可以在子类中重新实现这些函数。
9.2EventTypes
Mosteventstypeshavespecialclasses,notablyQResizeEvent,QPaintEvent,QMouseEvent,QKeyEvent,andQCloseEvent.EachclasssubclassesQEventandaddsevent-specificfunctions.Forexample,QResizeEventaddssize()andoldSize()toenablewidgetstodiscoverhowtheirdimensionshavebeenchanged.
Someclassessupportmorethanoneactualeventtype.QMouseEventsupportsmousebuttonpresses,double-clicks,moves,andotherrelatedoperations.
10.绘制系统
整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。
QPainter用来执行绘制的操作;QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间;QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。
QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的。
除非你需要自定义一个设备,否则你是不需要关心QPaintEngine这个类的。
我们可以把QPainter理解成画笔;把QPaintDevice理解成使用画笔的地方,比如纸张、屏幕等;而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了QPaintEngine类,这个类让不同的纸张、屏幕都能使用一种画笔。
Qt绘图系统定义了两个绘制时使用的关键属性:
画刷和画笔。
前者使用QBrush描述,大多用于填充;后者使用QPen描述,大多用于绘制轮廓线。
QPainter/QPainterDevice/QPixmap
10.1QPainter
(1)介绍:
Ø可以在QPaintDevice类上绘制各种图形;
ØQPaintDevice类表示QPainter的绘图设备(画布)。
QPaintDevice子类有QImage、QWidget等。
所以QPainter可以在QImage、QWidget上绘制图形;
ØQPainter只能在类对象的paintEvent()函数中绘制图形。
(2)类成员角色:
ØQPen:
用于绘制几何图形的边缘,由颜色、宽度、线风格等参数组成;
ØQBrush:
用于填充几何图形的调色板,由颜色和填充风格组成;
ØQFont:
用于文本绘制;
ØQPixmap:
绘制图片,可以直接读取图像文件进行像素访问,适合大图片;
ØQBitmap:
QPixmap的一个子类,主要用于显示单色位图;
(3)基础图形绘制相关函数:
成员函数
功能
成员函数
功能
drawPoint()
绘制点
drawChord()
绘制弦
drawLine()
绘制直线
drawPolygon()
绘制多边形
drawRect()
绘制矩形
drawRoundedRect()
绘制圆角矩形
drawArc()
绘制圆弧
drawPolyline()
绘制折线
drawEllipse()
绘制椭圆
drawConvexPolygon()
绘制凸多边形
drawPie()
绘制扇形
drawPixmap()
11.GraphicsViewFramework
QGraphicsScene/QGraphicsView
12.文件
在Unix/Linux中,路径的分隔采用正斜杠“/”,比如“/home/FYF”;而在Windows中,路径分隔采用反斜杠“\”,比如“C:
\Windows\System”。
在官方文档中,有这么一则说明:
QFileexpectsthefileseparatortobe‘/’regardlessofsystem.Theuseofotherseparators(e.g.‘\’)isnotsupported.
13.tr()函数
QStringtext1=QObject:
:
tr("hello");
QStringtext2=QString("hello");
tr是用来实现国际化,如果你为这个程序提供了中文翻译包(其中hello被翻译成中文"你好"),那么text1的内容将是中文"你好";如果你为程序提供且使用日文翻译包,那么text1的内容将是日文。
根据上述说法,这个tr()函数最起码在实际情况中用不着。
14.MinGW
MinGW和VC一样,是一个开发环境。
本来QT是Linux环境下的一个图形库,用来开发图形界面的应用程序。
而为了能让QT在Windows环境下依然能用,因此有了MinGW这个东西,其是MinimalistGNUforWindows的缩写。
15.图标说明