QT框架的C++编程Word格式文档下载.docx
《QT框架的C++编程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《QT框架的C++编程Word格式文档下载.docx(64页珍藏版)》请在冰豆网上搜索。
几套图形用户交互操作的可视化效果。
工作区模块
多文档界面(MDI)支持
OpenGL三维图形模块
在Qt中集成了OpenGL
网络模块
一些套接字,TCP,FTP和异步DNS查询并与平台无关的类
画布模块
为可视化效果,图表和其它而优化的二维图形领域
表格模块
灵活的,可编辑的表格/电子表格
XML模块
通过SAX接口和DOMLevel1的XML解析器
SQL模块
SQL数据库访问类
3、Qt的组成
Qt提供了一组范围相当广泛的C++类库,并包含了几种命令行和图形界面的工具,有效地使用这些工具可以加速开发过程。
QtDesigner:
Qt设计器。
用来可视化地设计应用程序界面。
QtLinguist:
Qt语言学家。
用来翻译应用程序。
以此提供对多种语言的支持。
Qmake:
使用此工具可以由简单的、与平台无关的工程文件来生成编译所需的Makefile。
QtAssistant:
关于Qt的帮助文件。
类似于MSDN。
可以快速地发现你所需要的帮助。
moc:
元对象编译器。
uic:
用户界面编译器。
在程序编译时被自动调用,通过ui_*.h文件生成应用程序界面。
qembed:
转换数据,比如,将图片转换为C++代码。
4、Qt的安装
安装的过程对于不同的Qt平台是不同的。
在Windows环境下安装Qt,需要先安装MinGW。
MinGW,即MinimalistGNUForWindows。
它是一些头文件和端口库的集合,该集合允许人们在没有第三方动态链接库的情况下使用GCC(GNUCompilerC)产生Windows32程序。
在基本层,MinGW是一组包含文件和端口库,其功能是允许控制台模式的程序使用微软的标准C运行时间库(MSVCRT.DLL),该库在所有的NTOS上有效,在所有的Windows95发行版以上的WindowsOS有效,使用基本运行时间,你可以使用GCC写控制台模式的符合美国标准化组织(ANSI)程序,可以使用微软提供的C运行时间扩展。
该功能是Windows32API不具备的。
下一个组成部分是w32api包,它是一组可以使用Windows32API的包含文件和端口库。
与基本运行时间相结合,就可以有充分的权利既使用CRT(CRuntime)又使用Windows32API功能。
实际上MinGW并不是一个C/C++编译器,而是一套GNU工具集合。
除开GCC(GNU编译器集合)以外,MinGW还包含有一些其他的GNU程序开发工具(比如gawkbison等等)。
在安装MinGW之后,再安装Qt,然后更改一下Windows系统的环境变量,就可以在Windows环境下使用Qt了。
如果想在VC环境下使用Qt,那么还需要进一步编译和设置,或者下载专门用于VC的QT版本。
有关此方面的信息请参考附录。
二、开始学习Qt
1、Hello,Qt!
我们以一个非常简单的Qt程序开始Qt的学习。
我们首先一行行的分析代码,然后我们将会看到怎样编译和运行这个程序。
1#include<
QApplication>
2#include<
QLabel>
3intmain(intargc,char*argv[])
4{
5QApplicationapp(argc,argv);
6QLabel*label=newQLabel("
HelloQt!
"
);
7label->
show();
8returnapp.exec();
9}
第1行和第2行包含了两个类的定义:
QApplication和QLabel。
对于每一个Qt的类,都会有一个同名的头文件,头文件里包含了这个类的定义。
因此,你如果在程序中使用了一个类的对象,那么在程序中就必须包括这个头文件。
第3行是程序的入口。
几乎在使用Qt的所有情况下,main()函数只需要在把控制权转交给Qt库之前执行一些初始化,然后Qt库通过事件来向程序告知用户的行为。
argc是命令行变量的数量,argv是命令行变量的数组。
这是一个C/C++特征。
它不是Qt专有的,无论如何Qt需要处理这些变量
第5行定义了一个QApplication对象App。
QApplication管理了各种各样的应用程序的广泛资源,比如默认的字体和光标。
App的创建需要argc和argv是因为Qt支持一些自己的命令行参数。
在每一个使用Qt的应用程序中都必须使用一个QApplication对象,并且在任何Qt的窗口系统部件被使用之前创建此对象是必须的。
App在这里被创建并且处理后面的命令行变量(比如在X窗口下的-display)。
请注意,所有被Qt识别的命令行参数都会从argv中被移除(并且argc也因此而减少)。
第6行创建了一个QLabel窗口部件(widget),用来显示“Hello,Qt!
”。
在Qt和Unix的术语中,一个窗口部件就是用户界面中一个可见的元素,它相当于Windows术语中的“容器”加上“控制器”。
按钮(Button)、菜单(menu)、滚动条(scrollbars)和框架(frame)都是窗口部件的例子。
窗口部件可以包含其它的窗口部件。
例如,一个应用程序界面通常就是一个包含了QMenuBar,一些QToolBar,一个QStatusBar和其它的一些部件的窗口。
绝大多数应用程序使用一个QMainWindow或者一个QDialog作为程序界面,但是Qt允许任何窗口部件成为窗口。
在这个例子中,QLabel窗口部件就是作为应用程序主窗口的。
第7行使我们创建的QLabel可见。
当窗口部件被创建的时候,它总是隐藏的,必须调用show()来使它可见。
通过这个特点我们可以在显示这些窗口部件之前定制它们,这样就不会出现闪烁的情况。
第8行就是main()将控制权交给Qt。
在这里,程序进入了事件循环。
事件循环是一种stand-by的模式,程序会等待用户的动作(比如按下鼠标或者是键盘)。
用户的动作将会产生程序可以做出反应的事件(也被称为“消息”)。
程序对这些事件的反应通常是执行一个或几个函数。
为了简单起见,我们没有在main()函数的结尾处调用delete来删除QLabel对象。
这种内存泄露是无害的,因为像这样的小程序,在结束时操作系统将会释放程序占用的内存堆。
下面我们来编译这个程序。
建立一个名为hello的目录,在目录下建立一个名为hello.cpp的c++源文件,将上面的代码写入文件中。
运行“开始程序QtbyTrolltechQtCommandPrompt”。
在命令行模式下,切换目录到hello下,然后输入命令:
qmake–project。
这个命令将产生一个依赖于工作平台的工程文件(hello.pro)。
再输入命令:
qmakehello.pro。
这个命令通过工程文件产生一个可以在特定工作平台上使用的makefile。
最后输入命令:
make来产生应用程序。
运行这个程序,可以得到如下的程序界面。
Qt也支持XML。
我们可以把程序的第6行替换成下面的语句:
QLabel*label=newQLabel("
<
h2>
i>
Hello<
/i>
"
fontcolor=red>
Qt!
<
/font>
/h2>
重新编译程序,我们发现界面拥有了简单的HTML风格。
如下图:
2、调用退出
第二个例子展示了如何使应用程序对用户的动作进行响应。
这个应用程序包括了一个按钮,用户可以点击这个按钮来退出程序。
程序代码与上一个程序非常相似,不同之处在于我们使用了一个QPushButton来代替QLabel作为我们的主窗口,并且我们将一个用户动作(点击一个按钮)和一些程序代码连接起来。
2#include<
QPushButton>
3intmain(intargc,char*argv[])
4{
5QApplicationapp(argc,argv);
6QPushButton*button=newQPushButton("
Quit"
7QObject:
:
connect(button,SIGNAL(clicked()),
8&
app,SLOT(quit()));
9button->
10returnapp.exec();
11}
Qt程序的窗口部件发射信号(signals)来指出一个用户的动作或者是状态的变化。
在这个例子中,当用户点击这个按钮的时候,QPushButton就会发射一个信号——clicked()。
一个信号可以和一个函数(在这种情况下我们把这个函数叫做“槽(slot)”)相连,当信号被发射的时候,和信号相连的槽就会自动执行。
在这个例子中,我们把按钮的信号“clicked()”和一个QApplication对象的槽“quit()”相连。
当按钮被按下的时候,这个程序就退出了。
3、窗口布局
在本小节,我们将用一个样例来展现如何在窗口中规划各个部件的布局,并学习使用信号和槽来使两个窗口部件同步。
这个应用程序要求输入用户的年龄,使用者可以通过一个旋转窗口或者一个滑块窗口来输入。
这个应用程序包括三个窗口部件:
一个QSpinBox,一个QSlider和一个QWidget。
窗口部件QWidget是程序的主窗口。
QSpinBox和QSlider被放置在QWidget中;
他们是QWidget的子窗口。
当然,我们也可以说QWidget是QSpinBox和QSlider的父窗口。
QWidget本身没有父窗口,因为它被当作一个顶级的窗口。
QWidget以及所有它的子类的构造函数都拥有一个参数:
QWidget*,这说明了它的父窗口。
下面是程序的代码:
QHBoxLayout>
3#include<
QSlider>
4#include<
QSpinBox>
5intmain(intargc,char*argv[])
6{
7QApplicationapp(argc,argv);
8QWidget*window=newQWidget;
9window->
setWindowTitle("
EnterYourAge"
10QSpinBox*spinBox=newQSpinBox;
11QSlider*slider=newQSlider(Qt:
Horizontal);
12spinBox->
setRange(0,130);
13slider->
14QObject:
connect(spinBox,SIGNAL(valueChanged(int)),
15slider,SLOT(setValue(int)));
16QObject:
connect(slider,SIGNAL(valueChanged(int)),
17spinBox,SLOT(setValue(int)));
18spinBox->
setValue(50);
19QHBoxLayout*layout=newQHBoxLayout;
20layout->
addWidget(spinBox);
21layout->
addWidget(slider);
22window->
setLayout(layout);
23window->
24returnapp.exec();
25}
第8行和第9行设置了QWidget,它将被作为程序的主窗口。
我们调用函数setWindowTitle()来设置窗口的标题栏。
第10行和第11行创建了一个QSpinBox和一个QSlider,第12行和第13行设置了它们的取值范围(我们假设用户最大也只有130岁)。
我们可以将之前创建的QWidget对象window传递给QSpinBox和QSlider的构造函数,用来说明这两个对象的父窗口,但是这么做并不是必须的。
原因是窗口布局系统将会自己指出这一点,自动将window设置为父窗口。
我们一会儿就可以看到这个特性。
在第14行和第17行,两个对于QObject:
connect()函数的调用确保了旋转窗口和滑块窗口的同步,这样这两个窗口总是显示同样的数值。
不管一个窗口对象的数值何时发生变化,它的信号valueChanged(int)就将被发射,而另一个窗口对象的槽setValue(int)会接受到这个信号,使得自身的数值与其相等。
第18行将旋转窗口的数值设置为50。
当这个事件发生的时候,QSpinBox发射信号valueChanged(int),这个信号包括一个值为50的整型参数。
这个参数被QSlider的槽setValue(int)接受,就会将滑块的值也设置为50。
由于QSlider的值被改变,所以QSlider也会发出一个valueChanged(int)信号并触发QSpinBox的setValue(int)槽。
但是在这个时候,QSpinBox不会再发出任何信号,因为旋转窗口的值已经被设置为50了。
这将有效地防止信号的无限循环。
从第19行到第22行,我们通过使用一个layout管理器对旋转窗口和滑块窗口进行了布局设置。
一个布局管理者就是一个根据窗口作用设置其大小和位置的对象。
Qt有三个主要的布局管理类:
QHBoxLayout:
将窗口部件水平自左至右设置(有些情况下是自右向左)。
QVBoxLayout:
将窗口部件垂直自上向下设置。
QGridLayout:
以网格形式设置窗口部件。
第22行我们调用QWidget:
setLayout()函数在对象window上安装布局管理器。
通过这个调用,QSpinBox和QSlider自动成为布局管理器所在窗口的子窗口。
现在我们明白为什么在设置子窗口时不用显式地说明父窗口了。
可以看到,虽然没有明显地给出任何窗口的大小和位置,但QSpinBox和QSlider是很完美地被水平依次放置的。
这是因为QHBox-Layout根据各个窗口的作用自动的为其设置了合理的大小和位置。
这个功能使我们从烦琐的界面调整中解放出来,更加专注于功能的实现。
Qt构建用户界面的方法很容易理解,并且有很高的灵活性。
Qt程序员最常用的设计模式是:
说明所需要的窗口部件,然后设置这些部件必须的特性。
程序员把窗口部件添加到布局管理器中,布局管理器就将自动地设置这些部件的大小和位置。
而用户界面的行为是通过连接各个部件(运用信号/槽机制)来实现的。
4、派生QDialog
我们现在开始尝试着在Qt里只用C++语言而不是借助界面设计器来完成一个对话框:
FIND。
我们将这个对话框作为一个类来完成,这么做的好处是我们使这个对话框成为了一个独立的,拥有自己的信号和槽的,设备齐全的组件。
程序的源代码由两部分组成:
finddialog.h和finddialog.cpp。
我们从头文件开始。
1#ifndefFINDDIALOG_H
2#defineFINDDIALOG_H
3#include<
QDialog>
4classQCheckBox;
5classQLabel;
6classQLineEdit;
7classQPushButton;
第1行,第2行(和第27行)的作用是防止头文件被重复包含。
第3行包含了QDialog的定义。
QDialog从QWidget继承而来,是Qt的对话框基类。
第4行到第7行是对我们将要用来填充对话框的对象的类的预定义。
一个预先的声明将会告诉C++编译器这个类的存在,而不用给出所有关于实现的细节。
然后我们定义FindDialog作为QDialog的一个子类:
8classFindDialog:
publicQDialog
9{
10Q_OBJECT
11public:
12FindDialog(QWidget*parent=0);
在类定义顶端出现了宏:
Q_OBJECT。
这对于所有定义了信号或槽的类都是必须的。
FindDialog的构造函数拥有Qt窗口类的典型特征。
参数parent声明了父窗口。
其默认值是一个空指针,表示这个对话框没有父窗口。
13signals:
14voidfindNext(constQString&
str,Qt:
CaseSensitivitycs);
15voidfindPrevious(constQString&
标记为signals的这一段声明了两个信号。
当用户点击对话框的“Find”按钮的时候,信号将被发射。
如果选项“Searchbackward”被选中,对话框将发射消息findPrevious();
相反的,对话框将发射消息findNext()。
关键字“signals”实际上也是一个宏。
C++预处理器将在编译器看到它之前就已经将它转换为了标准的C++。
Qt:
CaseSecsitivity是一个枚举类型。
它可以代表值Qt:
CaseSensitive和Qt:
CaseInsensitive。
16privateslots:
17voidfindClicked();
18voidenableFindButton(constQString&
text);
19private:
20QLabel*label;
21QLineEdit*lineEdit;
22QCheckBox*caseCheckBox;
23QCheckBox*backwardCheckBox;
24QPushButton*findButton;
25QPushButton*closeButton;
26};
27#endif
在类的private字段中,我们声明了两个槽。
为了实现这些槽,我们需要访问大多数对话框的子窗口,所以我们在私有字段中保留了这些子窗口的指针。
和signals一样,关键字slots也是一个构造后可以被C++编译器辩识的宏。
对于私有变量,我们使用了它们的类的预定义。
这是被编译器所允许的,因为他们都是指针,而我们在头文件中并不需要访问他们,所以编译器并不需要完整的类定义。
我们可以在头文件中包含使用这些类所需要的头文件(<
QCheckBox>
<
,等等),但是使用预定义可以在某种程度上加快编译过程。
现在我们来看源文件finddialog.cpp。
源文件里包括了FindDialog类的实现。
QtGui>
2#include"
finddialog.h"
首先,我们包含了<
。
这个头文件包含了对于Qt的GUI类的定义。
Qt包括一些模块,每一个模块都依赖于自己的库文件。
最重要的几个模块分别是QtCore,QtGui,QtNetwork,QtOpenGL,QtSpl,QtSvg和QtXml。
头文件<
包括了QtCore和QtGui模块中所有类的实现。
包含此头文件使我们不用单独地列出每个类所需要的头文件。
在filedialog.h中,我们也可以简单地包含<
,而不是像我们之前做的那样包括<
,并且给QCheckBox,QLabel,QLineEdit,QPushButton提供预定义。
这样似乎简单一些,但是在头文件中包含另外一个大的头文件是一个很坏的方式,尤其是在比较大的应用当中。
3FindDialog:
FindDialog(QWidget*parent)
4:
QDialog(parent)
5{
6label=newQLabel(tr("
Find&
what:
));
7lineEdit=newQLineEdit;
8label->
setBuddy(lineEdit);
9caseCheckBox=newQCheckBox(tr("
Match&
case"
10backwardCheckBox=newQCheckBox(tr("
Search&
backward"
11findButton=newQPushButton(tr("
&
Find"
12findButton->
setDefault(true);
13findButton->
setEnabled(false);
14closeButton=newQPushButton(tr("
Close"
在第4行,我们将参数parent传递给基类的构造函数。
然后我们创建子窗口。
对于所有的字符串我们都调用函数tr(),这些字符串被标记为可以翻译成别的语言。
函数tr()在QObject和每个含有Q_OBJECT宏的子类中被定义。
将没一个用户可见的字符串都用TR()包括起来是一个很好的习惯,即使你现在并没有将程序翻译为别的语言的计划。
对于Qt应用程序的翻译将在后述章节中详细呈现