《C++ GUI Qt 4 编程》 笔记(七)

第21章 创建插件

动态链接库
LIBS += -ldb_cxx
INCLUDEPATH += /usr/local/BerkeleyDb.4.2/include

QLibrary 动态加载dll

插件
常见的插件类型:
数据库驱动程序、图像格式、风格、文本编码解码器

实现一个插件
需要实现两种类:
插件类 提供访问插件功能(处理器类)的接口
处理器基类 插件提供的功能

.pro
TEMPLATE = lib
CONFIG += plugin // 指明是插件库而不是通用库

Qt应用程序在plugins目录中寻找插件比如 plugins/styles
如果需要将Qt插件配置到其他目录中
需要在代码中扩展搜索路径
QCoreApplication::addLibraryPath()
或设置QT_PLUGIN_PATH环境变量

自定义插件
1.定义接口

2. 定义插件

感知插件,加载插件

第22章 应用程序脚本

QtScript模块 ECMAScript (JavaScript标准)

1.把脚本读入QString
2.创建一个QScriptEngine对象,并设置应用程序相关的功能
3.执行脚本

QFileSystemWatcher

脚本:
pi.js
return 3.14;
cube.js
return x * x * x;

QSyntaxHighlighter

QUiLoader

扩展QVariant处理的类型
Q_DECLARE_METATYPE(QScriptValue)

第23章 平台相关特性

平台相关的编程接口
Windows Win32
Mac OS X Carbon
X11 Xlib

QWidget::winId() 返回平台相关的窗口句柄

QWidget::find() 返回指定窗口ID对应的QWidget

平台相关宏定义
Q_WS_MAC
Q_WS_X11
Q_WS_WIN
Q_WS_QWS (Qtopia)

系统版本
QSysInfo::WindowsVersion()
QSysInfo::MacintoshVersion()

编译器宏
Q_CC_MSVC

Qt/Windows桌面版 提供了ActiveQt框架,用以为ActiveX和Qt提供完美结合。
ActiveQt由两个模块组成:
QAxContainer 允许我们使用COM对象并且可以在Qt应用程序中嵌入ActiveX控件
QAxServer 允许我们导出使用Qt编写的自定义的COM对象和ActiveX控件

.pro
CONFIG += qaxcontainer
CONFIG += qaxserver

Q_ENUMS()宏
用来告诉moc在槽中使用的该类型为一个枚举类型

QAxObject封装一个COM对象
QAxWidget封装一个ActiveX控件
QAxBase为QAxObject和QAxWidget实现了COM的核心功能

编写服务器

当包括一个源于QObject类的多重继承的时候,必须总是把这个起源于QObject的类放在第一位,以便moc可以快速识别它。

Q_PROPERTY()宏 使用该宏声明的属性可以用setProperty()设置值

第24章 嵌入式编程

Qt/Embedded Linux (Qtopia Core)是为嵌入式Linux优化过的Qt版本

《C++ GUI Qt 4 编程》 笔记(六)

第17章 提供在线帮助

工具提示

状态提示 显示在状态栏上

What’s This? 文本帮助

当处于what’s this模式下时(windows 标题栏问号按钮 或shift + f1)
单击窗体,将显示设置的帮助文本

QWhatsThis::createAction();

当用户按下F1键或单击Help菜单项时,应用程序主窗口会调用help()槽

QTextBrowser

QWidget::setAttribute(Qt::WA_DeleteOnClose)
// 通常模式对话框不允许和这个应用程序中的其他任何窗口进行交互
// 以下代码允许这种交互
QWidget::setAttribute(Qt::WA_GroupLeader)

textBrowser->documentTitle();

Qt Assitant库
.pro
CONFIG += assistant

第三部分 Qt高级

第19章 Unicode

QTextCodec::codecForLocale() 获得本地字符集

让应用程序感知翻译
1. tr()
2. 程序启动时,载入一个翻译文件.qm

另一种方式:

lupdate工具

不要含有变量

应该这样

QT_TRANSLATE_NOOP(“上下文”, “xxx”);

禁止const char* 到QString的隐含转换
在包含任意Qt头文件之前预先定义:
QT_NO_CAST_FROM_ASCII
或在.pro中
DEFINES += QT_NO_CAST_FROM_ASCII

QLocale 提供本地化的数字和日期以及时间格式

动态改变语言
只需重新加载翻译文件,然后重新设置需要翻译的文本

翻译应用程序:
1. 运行lupdate,从应用程序的源代码中提取所有用户可见的字符串
2. 使用Qt Linguist翻译应用程序
3. 运行lrelease,生成二进制的.qm文件,应用程序可以使用QTranslator加载这个文件

在.pro中加入需要支持的语言
当第一次运行lupdate时会创建这两个文件xml格式
ts – translate source
qm – Qt Message
TRANSLATIONS = spreadsheet_de.ts spreadSheet_fr.ts

lupdate -verbose spreadsheet.pro

CODECFORTR = …
QTextCodec::setCodecForTr()

lrelease -verbose spreadsheet.pro

第19章 自定义外观

三种方法重新定义Qt内置窗口部件的外观
1. 子类化窗口部件类
2. 子类化QStyle或者一个预定义的风格比如QWindowStyle,Qt通过这种方法为不同平台提供基于平台的外观
3. Qt样式表 受CSS启发

样式表作用于上层的当前激活的QStyle上,因为创建样式表不引入任何子类,所以它们适合对现有窗口部件做微小的定制。

例如:
想在应用程序中的所有QLineEdit中使用黄色作为背景色

QObject::setProperty()

QStyle
内置样式类:
QStyle
|- QCommonStyle
|  |-QWindowStyle
|  |-QCleanlookStyle
|  |-QMacStyle
|  |-QPlastiqueStyle
|  |-QWindowsXPStyle
|  |-QWindowsVistaStyle
|
|- QMotifStyle
|- QCDEStyle

class MyPushButton : public QWidget

QApplication::setStyle() // 设置整个应用程序的样式
QWidget::setStyle() // 为个别窗口部件设置样式

drawControl()函数被各种QStyle的子类重新实现,用于绘制窗口部件
第20章 三维绘图 OpenGL

1. 子类化QGLWidget
2. 实现几个虚函数
3. 连接QtOpenGL OpenGL库

.pro
QT += opengl

OpenGL QPainter结合
在paintEvent()函数绘制
1. 创建一个QPainter
2. 使用QPainter绘制背景
3. 保存OpenGL状态
4. 使用OpenGL操作绘制场景
5. 恢复OpenGL状态
6. 使用QPainter绘制前景
7. 销毁QPainter

QGLWidget::renderText()

使用帧缓存对象生成叠加
基本思路:
1. opengl渲染到纹理
2. 将纹理绘制到窗口
3. 将选择框绘制到窗口
假如只有窗口大小改变时才重新opengl渲染
这时,假如选择框的大小改变,而窗口大小没有改变时,则只需要绘制一张纹理和一个选择框,模型并不需要频繁渲染。

《C++ GUI Qt 4 编程》 笔记(五)

第15章 网络

QFtp
QHttp

QTcpSocket QSslSocket
QUdpSocket

使用QCoreApplication而不是QApplication以避免连接到QtGui库

QUrl类提供了一个高级接口,用来提取URL的不同部分,如文件名称、路径、协议和端口

当所有请求都已处理完时,QFtp就发射done(bool)信号,bool表明是否有错误发生

FTP指令在Qt的事件循环中排队并等待执行。

QFtp提供的FTP指令函数
connectToHost()
login() close() list() cd() get() put() remove()
mkdir() rmdir() rename()

使用rawCommand() 可以执行任意FTP指令
ftp.rawCommand(“SITE CHMOD 755 fortune”)

QFtp信号
commandStarted(int) // int 指令ID号
commandFinished(int, bool)
stateChanged() // 只要连接进入了一个新状态就会发射该信号
done(bool) // 一旦指令队列变空,就会发射这个信号
listInfo(const QUrlInfo&) // 对list()处理的每一个文件调用该信号
如果发生错误,QFtp会自动清空指令队列,错误指令后面的指令将不会执行

.pro
QT += network

QUrlInfo urlInfo;
urlInfo.isSymLink()

QHttp
get() post() 是异步工作的,调用时立即返回,当控制权回到Qt事件循环时才会开始传输数据

QHttp貌似在Qt5中已经不存在了

QTcpSocket

连接成功后会发送connected()信号
连接失败会发送error(QAbstracSocket::SocketError)信号
readyRead()信号 只要QTcpSocket已经从服务器收到新数据,就会发射该信号

QTcpServer 信号
incomingConnection(int socketId)

QTcpServer
.listen(QHostAddress::Any, 6178); // any 表示 本地主机上的任意IP地址 0.0.0.0

基于行

发送数据使用QTextStream

QHostInfo::fromName()
QHostInfo::lookupHost()

UTP客户端

第16章 XML

QtXml模块的三个不同编程接口
QXmlStreamReader 一个用于读取格式良好的XML文档的快速解析器
DOM 将XML文档转换为应用程序可以遍历的树形结构
SAX 通过虚拟函数直接向应用程序报告解析事件

XML文件写入,三种方法:
1. 使用QXmlStreamWriter
2. 在内存中以DOM树的结构表示数据,并要求树结构将自己写到文件中
3. 手动生成XML

QXmlStreamReader
.readNext()
.isStartElement()
.isCharacters()

.pro
QT += xml

Qt的SAX类时对基于SAX2的java实现的模拟

QXmlSimpleReader
QXmlContentHandler
QXmlErrorHandler

继承自QXmlDefaultHandler
重写事件处理函数
startDocument()
startElement()
characters()
endElement()
endDocument()
fatalError()

XML保存

QXmlStreamWriter自动处理转义字符

《C++ GUI Qt 4 编程》 笔记(四)

第12章 输入与输出

QIODevice 基类

QFile
QTemporaryFile 临时文件
QBuffer 从QByteArray中读取或写入数据
QProcess 运行外部程序并处理进程间通信
QTcpSocket
QUdpSocket
QSslSocket 利用SSL/TLS在网络上传输加密数据流
后4个为顺序存储设备
前3个为随机存储设备 seek()

QDataStream 读写二进制数据
QTextStream 读写文本数据
这2个类考虑了字节顺序和文本编码等问题
比标准c++更加方便,标准c++将这些问题留给了程序员来处理。

QFile QDir QFileInfo

通过QFile打开文件
然后通过QDataStream对象存取

qRegisterMetaTypeStreamOperators<T>()

QIODevice

压缩解压缩
qCompress()
qUncompress()
QtIOCompressor()

QTextStream
处理了字符集编码转换、不同的行尾符的转换
还支持C++基本数字类型,处理数字与字符串之间的转换

stream.setCodec(“UTF-8”);

可以应用在QString上
QString str;
QTextStream(&str);

QDir 提供与平台无关的遍历目录并获得有关文件信息的方法

QDir::convertSeparators() 将斜线转为针对具体平台的正确的分隔符

QDir::currentPath();
QDir::homePath();
QCoreApplication app(argc, argv);
QStringList args = QCoreApplication::arguments();

dir.entryInfoList();
dir.rename();
dir.exists();
dir.mkdir();
dir.rmdir();

QFile::remove();
QFile::exists();

QFileSystemWatcher可以通过发送directoryChanged()、fileChanged()信号,在目录或者文件发生任何改变时通知我们。

QFile可以使用嵌入资源 e.g. :/datafiles/file.dat

进程间通信
QProcess允许我们执行外部程序并且和它们进行交互,这个类时异步工作的,且它在后台完成的工作。当外部进程得到数据或者已经完成时,QProcess会发出信号通知我们。

QDir::toNativeSeparators(fileName);

QProcess信号
readyReadStandardError()
finished()
error()

QTemporaryFile临时文件

QProcss::execute()静态函数运行外部程序并等待外部进程完成。

process.waitForStarted()
process.waitForFinished()

Windows下的ActiveQt扩展程序

如果想启动用户喜欢的网页浏览器或电子邮件客户端程序,只需要:
QDesktopServices::openUrl()

第13章 数据库

1. QSqlQuery 提供了一种直接执行任意SQL语句并处理其结果的方式
2. QSqlTableModel QSqlRelationalTableModel

数据库驱动
QMYSQL
QOCI 甲骨文公司
QODBC
QSQLITE SQLite3
QSQLITE2

query.numRowsAffected()

Oracle风格语法

ODBC风格语法

高级界面接口 QSqlTableModel

.pro文件
QT += sql

QDataWidgetMapper
第14章 多线程

子类化QThread并且重新实现run()函数

QThread成员函数
terminate() 终止线程执行
isRunning()
wait()

线程同步

QMutex 每次只能有一个线程可以访问同一个变量
QReadWriteLock 允许执行多个读取访问而不会影响性能
QSemaphore 用于保护(guard)一定数量的相同资源
QWaitCondition 允许一个线程在满足一定的条件下触发其他多个线程

QMutexLocker 构造函数锁定,析构函数解锁
QMutexLocker locker(&mutex);

QReadLocker
QWriteLocker

semaphore信号量的一个典型应用场景是:
当两个线程间传递一定量的数据时,这两个线程会使用某一特定大小的共享唤醒缓冲器。

线程局部存储
QThreadStorage<T>
.hasLocalData()
.setLocalData()
.localData()

与主线程通信
主线程是唯一允许创建QApplication或QCoreApplication对象,并且可以对创建的对象调用exec()的线程。

以上同步技术没有一个可以用来与主线程进行通信,因为它们会锁住事件循环并且会冻结用户界面。

使用信号和槽与主线程通信
例如:
在一个图像处理软件中,图像保存在线程对象中,在界面上选择对图像应用的变换时,主线程将包含该事务的事务对象添加到线程对象的事务列表中,线程对象后台对图像进行变换,当变换完成后通知主线程

如果需要删除一个存在于不同线程中的QObject对象,则必须调用线程安全的QObject::deleteLater()函数,它可以置入一个延期删除事件。

事件循环
QThread::exec()
QProcess::waitForFinished()
QAbstractSocket::waitForDisconnected()

可重入类:
类的多个实例可以安全地在多个线程中访问。
QWidget和它的子类都是不可重入的,这样造成的后果之一就是我们不能在一个来自次线程的窗口部件上直接调用函数。
可以通过发送信号或者:

《C++ GUI Qt 4 编程》 笔记(三)

第10章 项视图类

MVC
模型代表数据集,它对需要查看数据的获取以及任何存储的改变负责。
每种类型的数据集都有自己的模型,但不管底层的数据集是什么样子,模型提供给视图的API都是相同的。
视图代表的是面向用户的那些数据。
控制器是用户和视图之间的媒介,它把用户的操作转换为浏览或者编辑数据的请求,这部分数据是根据需要由视图传送给模型的数据。

通过把一个模型注册到两个或者多个视图,就可以让用户使用不同的方式查看数据以及和数据交互。

Qt对于多个视图会自动保持同步,对一个视图的改变会影响到全部视图。

例如:QTableView和QSqlTableModel可以组合在一起使用。

QDialog::done()

预定义模型类
QStringListModel 字符串列表
QStandardItemModel 任意的分层次的数据
QDirModel 封装本地文件系统
QSqlQueryModel 封装一个SQL结果集
QSqlTableModel SQL表
QSqlRelationTableModel 利用外键封装一个SQL表
QSortFilterProxyModel 排序筛选另一个模型

QRegExp::PatternSyntax syntax = …;
QRegExp regExp(text, Qt::CaseInsensitive, syntax);

自定义模型
reset() 告诉任何一个使用这个模型的视图,它们所有的数据都无效了

在模型中调用emit dataChanged()将通知视图更新

委托delegate 为MVC中的控制器
设置到视图上

QAbstractItemDelegate
createEditor()
setEditorData()
setModelData()
paint()

假设一个表视图,某些单元格显示的是时间,当编辑时需要显示一个时间控件,某些单元格需要显示一个下拉列表框
重写createEditor()创建一个所需的编辑控件
重写setEditorData()将模型数据设置到编辑控件
重写setModelData()将编辑控件中的值设置到模型数据
第11章 容器类

可以使用STL
也可以使用Qt容器类
Qt容器类
1. 在所有平台表现一致
2. 易于使用的迭代器类
3. 在Qt/Embedded Linux支持的一些硬件平台上,通常只能使用Qt容器

QList<T> 结合了以上两个容器的优点,支持随机访问。

QStringList 是QList<QString>的子类

QStack<T>
QQueue<T>

派生自QObject的Qt类无法放入以上容器中,因为没有复制构造函数和赋值操作符

java风格的迭代器:
只读迭代器
QVectorIterator<T>
QLinkedListIterator<T>
QListIterator<T>
读写迭代器
QMutableVectorIterator<T>

STL风格迭代器
QList<T>::iterator
QList<T>::const_iterator
QList<T>::begin()

Qt对所有的容器和许多其他类都使用隐含共享,包括QByteArray QBrush QFont QImage QPixmap QString,这使得这些类不论是作为函数参数还是作为返回值,都可以非常有效地传递。

编程习惯:
使用at()而不是[]操作符,原因:为了使隐含共享的作用发挥得最好
STL风格迭代器尽量使用const_iterator constBegin() constEnd()

QMap<K, T> // K类型必须提供operator<()
QMultiMap<K, T>
QHash<K, T> // 更快的查找速度,operator==()
// 为键值提供返回哈希值的全局qHash()函数
QCache<K, T>
QSet<K>

// 分别返回键和值的QList
QMap<K, T>::keys()
QMap<K, T>::values()

遍历

通用算法
<QtAlgorithms>
大部分都是在STL风格迭代器上工作

STL的<algorithm>也可以用在Qt容器类上

qFind()
qBinaryFind() 假设项都是以升序的顺序排序
qFill()
qCopy()
qSort() 小于号,也可以用qGreater<T>()
qStableSort() 稳定排序,相同的项排序后顺序不变
qDeleteAll() 对容器中的指针调用delete
qSwap()

<QtGlobal>
qAbs() 绝对值
qMin()
qMax()

格式化字符串

arg()的重载可以处理各种类型

数字转为字符串

字符串转为数字

在控制台上打印
qDebug() << str; <QtDebug>

str.mid()
str.left() str.right()
str.indexOf()
str.startsWith()
str.endsWith()
str.toLower()
str.replace()
str.remove()
str.insert()
str.trimmed()
str.simplified() 去掉头尾的空格,中间的连续空格只留一个空格
str.split()
strList.join() QStringList
str.isEmpty()
str.length()
str.fromAscii() str.toAscii()
qPrintable(str) => str.toAscii().constData()

QByteArray对于存储原始的二进制数据以及8位编码的文本字符串非常有用。

QVariant 以降低效率及可读性为代价

QPair<T1, T2>