第一章 hello,Qt
#include <QApplication>
2 #include <QLabel>
3 int main(int argc, char *argv[])
4 {
5 QApplication app(argc, argv);
6 QLabel *label = new QLabel("Hello Qt!");
7 label->show();
8 return app.exec(); }
第二章 创建对话框
1:emit为发射信号;
2:当将子布局对象添加到父布局对象中去,子布局对象就会自动重定义自己的父对象。即将主布局装到对话框中时,它就会成为对话框的子对象,于是它的所有子窗口部件就会重定义自己的父对象,从而变成对话中的子对象;
注:Qt会在删除父对象的时候自动删除其所属的所有子对象;
3:信号和槽
信号和槽机制是Qt编程的基础。它可以让应用程序编程人员把这些互不了解的对象绑定在一起。
槽与普通的C++函数几乎是一样的,可以是虚函数;可以被重载;可以是公有的。保护的或私有的,也可以被其他C++函数直接调用;并且,它们的函数可以是任意类型。
槽与普通的C++函数的区别:槽可以与信号连接在一起,(信号和槽函数必须有着相同的参数类型,这样信号和槽函数才能成功连接),在这种情况下,每当发射这个信号的时候,就会自动调用这个槽。Connect()语句如下: Connect(sender,SIGNAL(signal),receiver,SLOT(slot));
sender和receiver是QObject对象指针,signal和slot是不带参数的函数原型。SIGNALE()和SLOT()宏的作用是把他们转换成字符串。
如setupUi()函数建立下述连接:
Connect(lineEdit,SIGNAL(testChanged(constQString&)),this,SLOT(on_lineEdit_testChanged()))
信号和槽连接的可能性有以下几种情况:
1)一个信号可以连接多个槽;
2)多个信号可以连接一个槽;
3)一个信号可以与另外一个信号相连接;
4)连接可以被删除;
第三章 创建主窗口
1:创建菜单和工具栏的步骤:
1)创建并且设置动作;
2)创建菜单并且把动作添加到菜单上;
3)创建工具栏并且把动作添加到工具栏上;
注:一个动作就是一个可以添加到任意数量的菜单和工具栏上的项。
2:在Spreadsheet(电子制表)中,动作是在createActions()函数中创建的,相关程序代码:
void MainWindow::createActions()
...{
newAction = new QAction(tr("&New"), this);
newAction->setIcon(QIcon(":/images/new.png"));
newAction->setShortcut(tr("Ctrl+N"));
newAction->setStatusTip(tr("Create a new spreadsheet file"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
3:模态对话框和非模态对话框
非模态窗口:就是运行在应用程序中对于任何其他窗口都独立的窗口;
非模态(modeless)对话框:一个无模态的对话框就是在程序运行过程中不依赖其他窗口是否显示的对话框(创建无模式对话框后,一般要连接信号和槽函数用来响应用户输入),Find对话框是一个非模态对话框;
模态对话框:模态对话框就是弹出后,在关闭之前,它阻止程序的其他消息和其他进程的干扰,也不能切换到其他窗口。(Go-to-Cell,Sort对话框是一个模式对话框)
第四章 : 实现应用程序的功能
1:在QMainWindow的中心区域可以放置各类控件:
1)使用标准Qt控件;
2)使用用户自定义控件;
3)使用带有布局管理器的空白控件;
4)使用分隔条;
5)使用MDI工作控件;
第五章 :用户自定义窗口部件
1:在某些情况下,我们发现有些Qt控件通过设置它的属性或者函数不能满足我们的要求,还需要更多的要求。有两种解决方法:
1)对相关的窗口部件进行子类化并且让它们满足我们的需要;
2)通过对现有窗口部件的组合构建而成的自定义窗口部件;
2:由Qt控件组合而成的用户控件可以用Qt 设计师中实现:
1)使用“Widget”模板新建一个新窗体;
2)把一些必需的窗口部件添加到这个窗体上,并对它们进行摆放;
3)设置一些进行信号和槽连接
4)如果通过信号和槽不能获得所需的行为,则只需在类中添加一些必要的代码即可--这个类需要从QWidget类和uic生成的类中派生出来;
第六章 布局管理
1:Qt提供了多个用于在窗体中摆放窗口部件的类:QHBoxLayout,QVBoxLayout,QGridLayout和QStackLayout。能够执行布局管理其他的类有QSplitter,QScrollArea,QMainWindow,QWorkspace,这些类的共同特点是提供了更加灵活的布局方式,在一定程度上用户能够控制窗体内控件的大小。
2:使用Qt布局的另一个原因是:它们可以确保窗体能够自动适应于不同的字体,语言和系统平台。如果用户改变了系统的字体设置,那么该应用程序的窗体能立即作出反应,并在必要的情况下改变自己的大小。并且如果将应用程序的用户接口翻译成另一种语言,这些布局类就会考虑窗口部件中翻译的内容,以尽量避免文件被截断的现象发生。
3:用于管理子窗口布局的三种方法:
1)绝对位置法:是一种最原始的摆放窗口部件的方法。这可通过对窗体的各个子窗口部件分配固定的大小和位置以及对窗体分配固定的大小实现;
2)人工布局法:还需要给定窗口部件的绝对位置,人工布局方法给定的大小尺寸总可以与窗口的大小成比例。通过重新实现窗体的resizeEvent()函数。该函数可设置窗体中的子窗口部件的几何形象,以此实现人工布局法;
3)布局管理器:会为每种类型的窗口部件提供一些合理的默认值,并会考虑没一个窗口部件的大小提示,也会考虑最大,最小尺寸,并且会自动通过调整布局来相应字体的变化,内容的改变以及窗口大小的调整;
最重要的三种布局管理器:QHBoxLayout,QVBoxLayout,QGridLayout。它们是从QLayout中派生出来。
4:大小策略
一个窗口部件的大小策略会告诉布局系统应该如何对它拉伸会压缩,它既包含一个水平分量又包含一个垂直分量,常用值如下;
1)Fixed:该窗口部件不能被拉伸或压缩,其大小尺寸保持在提示的尺寸;
2)Minimum:该窗口部件的大小即是所提示的最小大小,但可拉伸以填充尽可能多的空间;
3)Maximum:该窗口部件的大小即是所提示的最大大小,但可压缩;
4)Preferred:该窗口部件的大小即是其合适的大小,但可拉伸或压缩;
5)Expanding:可拉伸或压缩该窗口部件,且希望变得更长更高;
5:拉伸因子:可用来说明在增大窗体时,对不同的子窗口部件应使用的不同放大比例;
6:分组布局的作用:QStackLayout类可以对一组子窗口部件进行摆放,或者对它们进行“分页”,而且一次只显示一个,而把其他的子窗口部件或者分页都隐藏起来。
7:切分窗口的作用:QSplitter是一个可以包含一些其他窗口部件的窗口部件。在切分窗口中的这些部件会通过切分条而分割开。用户可通过拖动这些切分条来改变切分窗口中子窗口部件的大小。切分窗口在应用程序中的表现,主要实现下图,对应源代码:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextEdit *editor1 = new QTextEdit;
QTextEdit *editor2 = new QTextEdit;
QTextEdit *editor3 = new QTextEdit;
QSplitter splitter(Qt::Horizontal);//水平切分窗口
splitter.addWidget(editor1);
splitter.addWidget(editor2);
splitter.addWidget(editor3);
...
splitter.show();
return app.exec();
}
8:滚动区域的作用:QScrollArea类提供了一个可以滚动的视口和两个滚动条。QScrollArea会以窗口部件的当前大小来显示它,或者在没有重新改变窗口部件大小的时候以它的大小来显示它。通过调用setWidgetResizable(true),可以告诉QScrollArea要自动重新改变该窗口的大小,以利用超过他的大小提示之外的任何多余空间。
9:停靠窗口
停靠窗口(dock window):是指一些可以停靠在QMainWindow中或是浮动为独立窗口的窗口。每一个停靠窗口都有自己的标题栏,通过拖拽这一标题栏,用户可以把停靠窗口从一个停靠区域移动到另一个停靠区域。在Qt中,可停靠窗口是QDockWidget的一个实例。
10:多文档界面(Mlitiple Document Interface,MDI)
多文档界面程序或MDI程序:在主窗口的中央区域能够提供多个文档的那些应用程序。在Qt中,一个多文档界面程序通过QMdiArea类作为中央窗口部件,并通过让每一个文档窗口都成为这个QMdiArea的子窗口部件创建得到。
第7章 事件处理
1:事件(event):是由窗口系统或者Qt自身产生的,用以相应所发生的各类事件。
2:几种常见的事件:键盘或鼠标事件,绘制事件,定时器事件等。
3: 可以在Ticker的构造函数中调用startTimer()。但是在控件可见以后再启动,能够节省一些资源。 (P132)
void Ticker::timerEvent(QTimerEvent *event){
if (event->timerId() == myTimerId) {
++offset;
if (offset >= fontMetrics().width(text()))
offset = 0;
scroll(-1, 0);}
else {
QWidget::timerEvent(event);}}
函数timerEvent()由系统以一定间隔进行调用的。把offset增加1来模仿文字的移动,增加到标语的宽度时文字的宽度是重新设置为0。然后调用scroll()把控件向左滚动一个象素。也可以调用update(),但是scroll()更加高效,它对可见的象素进行移动,只是对需要新绘制的地方调用绘制事件。
4:Qt中事件处理和事件过滤方法
共有5个级别的事件处理和事件过滤方法
1)重新实现特殊的事件处理器(paintEvent()函数用于线,圆等的实现);
2)重新实现QObject::event();
3)在QObject中安装事件过滤器;
4)在QApplication对象中安装事件过滤器;
5)子类化QApplication并且重新实现notify();
5:事件传递顺序:
(1)从子对象传到父对象的过程:如果事件到达它的目标对象之前没有得到处理,或者也没有被它自己的目标对象处理,那么就会重复整个事件的处理过程,但这次会把目标对象的父对象当做新的目标对象。这样一直继续下去,从父对象再到父对象的父对象,直到这个事件完全得到处理或者是达到最顶层的对象为止;
下图给出了一个按键事件是如何从子对象传到父对象的过程:当用户按下一个键时,这个事件首先发给拥有焦点的当前窗口部件,即右下角的QCheckBox.如QCheckBox没有处理该事件,Qt就把它发送给QGroupBox,直到最后的QDialog对象。
6:处理密集时的响应保持方法有两种:
1)使用新线程:一个线程用于处理应用程序的用户界面,另一个线程用于执行文件的保存操作(或者其他的任意耗时操作);
2)在文件保存的代码中频繁调用QApplication::processEvents(),这个函数告诉Qt处理所有那些还未处理的各类事件,后再将控制权返还给调用者。
第8章 二维图形
1: 二维图形的绘制方法(QPainter、paintEvent())
要在绘图设备(paint device,一般是一个控件)上开始绘制,我们只要创建一个QPainter,把绘图设备指针传给QPainter对象。绘制的方式由QPainter的设置决定。设置的一部分是从绘图设备得到的,其他是初始化时的默认值。使用QPainter的draw...()函数可以绘制各种各样的图形。重新实现QPainter::paintEvent()可用于定制窗口部件,并任意的控制它们的外观。
2:绘图设备(QWidget、QPixmap、QImage)
3:QPainter的三个主要设置(画笔、画刷、字体)及相应的类(QPen/QBrush/QFont)
画笔:用来画线和边缘。它包括颜色,宽度,线型,拐点风格以及连接风格;
画刷:用来填充几何形状的图案。它一般由颜色和风格组成,但同时也可以是纹理或者一个渐变;
字体:用来绘制文字。字体有许多属性,包括字体簇和磅值大小;
可以随时调用QPen,QBrush或者QFont对象的setPen().setBrush()和setFont(0来修改这些设置;
4:Qt支持三种类型的渐变:线性渐变,辐射渐变,锥形渐变。
5:坐标系统变换中的相关概念
(1)窗口与视口:窗口和视口是紧密联系在一起的视口是物理坐标系下指定的任意矩形;窗口也是指同一矩形,只不过是在逻辑坐标。当绘制图形时,在逻辑坐标系下指定的点,这些坐标都是基于当前的窗口-视口设定并以线性代数的方式转换为物理坐标。
(2)窗口设置:默认情况下被设置为矩形。
(3)世界变换(world transform):是在窗口-视口转换之外使用的变换矩阵。它允许移动、缩放。旋转或者拉伸绘制的项。
(4)坐标变换:就是给painter加上一些变换矩阵,坐标变换可以看做是painter当前的一个状态。一种比较简单的方式是使用QPainter的translate(),scale(),rotate()和shear()这些简便函数。如果想重复相同的变换,可以先保存到QTransform对象中,在需要变换时,再把世界变换设置到绘制器上。
第9章 拖放
1:拖放:是在一个应用程序内或多个应用程序之间传递信息的一种直观的现代操作方式。(功能:为剪贴板提供支持,还提供数据移动和复制的功能)
2:拖放操作中两个动作及对应的Qt事件
(1)拖放操作中两个动作:拖动和放下。
(2)对应的的Qt事件:QDadgLeaveEvent()和QDropEvent()等事件发生;
实例:介绍如何让一个Qt应用程序接受由另一个应用程序执行的一个拖动操作。该Qt应用程序是一个以QTextEdit作为中央窗口部件的主窗口程序,从别的地方拖动一个文件夹且在此应用程序中放下,文本文件就会载入到QTextEdit中。
以下是这个实例中MainWindow类的定义:
Class MainWindow : public QMainWindow
{
Q_OBJECT
Public:
MainWindow ();
Protected:
Void dragEnterEvent(QDragEnterEvent *event);
Void dropEvent(QDropEvent *event);
Private:
Bool readFile(const QString &fileName);
QTextEdit *textEdit;
};
//textEdit设为中央窗口,它接受其他窗口拖过来的文件
MainWindow ::MainWindow ()
{
textEdit =new QTextEdit;
sentCentralWidget(textEdit);//把textEdit设为中央窗口
textEdit->setAcceptDrops(false);
setAcceptDrops(true);
setWindowTitle(tr(“Text Editor”));
}
第11章 容器类
1:容器类:通常是用于在内存中存储给定类型的许多项的模板类,。Qt容器的主要优点是:它们在所有的平台上运行时都表现的一致,并且它们都是隐含共享的。
2:连续容器:能连续地存储项。如QVector(T)、QLinkedList(T)、QList(T)、QStack(T)、Queue(T)等都是连续容器;
QVector(T):是一种与数组类似的数据结构,它可以把项存储到内存中相邻近的位置;
QLinkedList(T):是一种把项存储到内存中不相邻近的位置的数据结构;
QList(T):是一个“数组列表”,结合上述二者的优点,可支持随机访问;
QStack(T):是一个可以提供push(),pop()和top()的向量;
QQueue(T):是一个可以提供enqueue(),dequeue()和head()的列表;
3:关联容器:存储键值对,可以保存任意多个具有相同类型的项,且他们由一个键索引。如QMap<K,T>、QHash<K,T>等的关联容器;
QMap<K,T>:似乎一个以升序键顺序存储键值的数据结构。
QHash<K,T>:是一个在哈希表中存储键值对的数据结构。
4:两种类型的迭代器(用于遍历存储在容器中的项):Java风格的迭代器和STL风格的迭代器。
Java风格的迭代器又有两种类型:只读迭代器和读-写迭代器。
5:通用算法:可以在任意容器上执行相关操作
(1)qSort()算法:对一个连续容器进行排序;
(2)qBinaryfind():在经过排序的连续容器上执行一个二进制搜索;
(3)qFind()算法在容器类中查找一个特定值,有匹配的项,返回一个与其匹配的指向第一项的迭代器;如无,则返回“end”;
(4)qFill()算法采用一个特定值组装一个容器;
(5)qCopy()算法:将一个容器类的值复制到另一个容器类中,也可用来在同一个容器类中复制值,只要数据来源范围与目标范围不重叠;
(6)Qsort()算法:以升序排列容器中的类;
(7)qTtableSort():与Qsort()算法类似,但还可以保证进行对等比较的项在排序之后表现出与之相同的顺序;
(8)qDeleteAll()算法:对每一个存储在容器中类中的指针调用delete。
6:字符串的基本使用:
Qt中字符串的实现:QString,16位,可以嵌入“/0”,可以在行数据的末端自动预分配内存空间。QString为连接两个字符串提供了一个二进制+操作符,还为在字符串后追加字符串提供了+=操作符。通过使用QString::number()静态函数,QString可以将数字转换为字符串。
第12章 输入与输出
1:QIODevice是一个封装能够读写字节块“设备”的提取器,Qt通过QIODevice为输入输出提供支持。Qt包括如下的QIODevice子类及其作用:
(1)QFile:在本地文件系统和嵌入式资源中存取文件;
(2)QTemporaryFile:在本地文件系统中创建并存取临时文件;
(3)QBuffer:从QByteArray中读取或写入数据;
(4)QProcess:运行外部程序并处理进程间通信;
(5)QTcpSocket:利用TCP在网络上传输数据流;
(6) QUdpSocket:在网络上发送和接收UDP数据报;
(7)QSslSocket:利用SSL/TLS在网络上传输加密数据流;
2:文本文件和二进制文件读写操作
QDataStream:用来读取二进制数据;
QTextStream:用来读写文本数据;
3:嵌入资源:利用Qt在应用程序的可执行文件中嵌入的二进制数据或文本;
第13章 数据库
1:连接和查询
在执行SQL查询之前,必须建立与数据库的连接。通常情况下,是在应用程序开始时所调用的一个单独的函数中建立数据库连接,如:
Bool createConnection()
{
QSlDatabase db=QSlDatabase::addDatabase(“QMYSQL”);
db.setHostName(“mozart.konkordia.edu”);
db.setDatabaseName(“musicdb”);
db,setUserName(“gbatstone”);
db.setPassword(“T17aV44”);
If(!db.open())
{
QMessageBox::critical(0,QObject::tr(“Database Error”),db.lastError().text());
Return false;
}
Return true;
}
2:数据库和网络应用程序中,在pro文件中分别要加入什么模块
()(2)对于使用SQL类的应用程序中,需要将如下的命令行添加到其.pro中:
QT +=sql
可确保应用程序可以连接到QtSql中。
3:利用SQL语句Qt数据库应用程序的基本操作步骤
建立与数据库的连接、查询、取结果
第14章 多线程
1:线程是进程中的一个实体,是程序执行流的最小单元,
在多线程应用程序中,图形用户界面运行于它自己的线程中,而另外的事件处理过程则会发生在一个或多个线程中。
2:Qt包含的一些线程相关类:
(1)QThread:提供开始一个新线程的方法;
(2)QThreadStorage::提供逐线程数据存储;
(3)QMutex:提供相互排斥的锁或互斥量;
(4)QMutexLocker:一个便利类,可自动对QMutex加锁与解锁;
(5)QReadLocker与QWriteLocker:一个便利类,可自动对QMutexLocker进行加锁与解锁;
(6)QSemaphore:提供一个整型信号量,是互斥量的泛化;
(7)QWaitCondition:提供一种可以使线程被另一线程唤醒之前一直休眠的方法;
3:Qt提供的几中用于同步的类:QMutex,QReadWriteLock,QSemaphore和QWaitCondition。
4:lock()函数:来锁住互斥量(mutex);
trylock()函数:如该互斥量已经锁住,它会立即返回;
QreadWriteLock:是一个同步类,允许同时执行多个读取访问而不会影响性能;
5:解决生产者和消费者线程同步问题:
(1)使用QWaitCondition和QMutex。QWaitCondition允许一个线程在满足一定的条件下触发其他多个线程,使得比只使用互斥量提供更为准确的控制;
(2)让生产者线程填满缓冲器,后等待消费者线程读取完缓冲器中全部数据为止;
6:互斥问题
(1)Qt提供了方便的QMutexLocker类来简化对互斥量的处理,QMutexLocker的构造函数接受QMutex作为参数将其锁住其析构函数对该互斥量进行解锁;
(2)对于每次只能有一个线程访问同一变量,可以使用同步类QWriteLocker,它能同时执行多个存取访问而不会影响性能;
第15章 网络
1:QFtp和QHttp两个类与FTP和HTTP协议配合使用,使文件的下载和上传变得容易;
QTcpSocket和QUdpSocket类:它们实现TCP和UDP传输协议;
QtcpServer:在创建服务器应用程序中,需QtcpServer类来处理引入的TCP连接。