QT 开发基础知识(八)
十七、附录 A:第三方工具
T 他的附录向你展示了一些第三方工具。一个大型的项目社区是围绕 Qt 构建的,这里展示的工具只是可用工具的一小部分。目的不是向您展示它们是如何使用的,而是向您展示可用工具的多样性。提到的每个项目都有很好的文档,并且很容易学习。
技术应用 Qt Widgets:Qwt
- 类别:小部件和类
- 网址:
[
qwt.sf.net](http://qwt.sf.net)
- 许可证:Qwt 许可证——LGPL 的慷慨版本
Qwt 是技术应用程序中使用的类和小部件的集合。小部件包括刻度盘、滑块、旋钮、图表、刻度和图例。提供的小部件通过插件与 Designer 很好地集成在一起。
在图 A-1 中可以看到 Qwt 的一些示例截图,其中显示了 Qwt 提供的一些表盘。这些刻度盘与滚轮和滑块结合在一起,可以很容易地指定数值。然而,Qwt 的真正威力在于它的绘图能力。您可以创建散点图、曲线图和直方图,带或不带等高线。所有这些图的数据都是通过QwtData
类或其后代提供的。通过继承QwtData
类,您可以计算要动态绘制的数据,然后将其提供给适当的绘图小部件。
**图 A-1。**Qwt 示例中的小部件和情节
wwWidgets
- 类别:小工具
- 网址:
[
www.wysota.eu.org/wwwidgets](http://www.wysota.eu.org/wwwidgets)
- 许可证:GPL
wwWidgets 库用一系列小部件补充了 Qt。这些小部件关注 Qt 从一开始就没有填充的区域——颜色选择小部件、屏幕键盘等——但也关注常见的组合小部件,如启动提示小部件。图 A-2 中显示了设计师会议的示例。这些小部件节省了时间,因为它们不必在每个新项目中都重新发明。
wwWidgets 库与 Qt 的其余部分集成得非常好——无论是在设计器中还是在构建系统中。当它被安装时,它会将自己添加到 Qt 安装中,所以您需要做的就是在您的项目文件中添加CONFIG += wwwidgets
——就像使用 Qt 模块一样简单。
图 A-2。 设计师会议中的一些 ww widgets
QDevelop
- 类别:开发环境
- 网址:
[
www.qdevelop.org](http://www.qdevelop.org)
- 许可证:GPL
QDevelop 是一个适用于 Qt 的真正的跨平台集成开发环境。它为 Qt 支持的所有平台提供了一个通用的开发环境。您可以在图 A-3 中看到一个示例会话。
QDevelop 的优势包括使用 GNU 调试器(gdb)调试应用程序的能力,处理 QMake 项目的能力,使用 ctags 提供代码完成和方法列表的能力,以及基于插件的架构。
注意要在 Windows 平台上使用 gdb,必须先安装(详情可以在 QDevelop 网站上找到)。
图 A-3。 QDevelop 在行动
ctags 对代码完成和方法列表的依赖性意味着接口可能会很慢,因为 ctags 是作为外部进程运行的,QDevelop 在这些功能实际工作之前会等待它完成。
QDevelop 确实有一个烦人的 bug。当请求帮助一个 Qt 类的成员函数时,它失败了。在寻找帮助时,您必须始终将光标放在实际的类名上。
当启动 Qt Assistant 来提供帮助时,它会作为一个单独的应用程序启动。QDevelop 将 Designer 和 Qt Assistant 作为外部应用程序与 QDevelop 应用程序并行运行。这很好,但是你必须手动地在应用程序之间来回切换。
Edyuk
- 类别:开发环境
- 网址:
[
edyuk.sf.net](http://edyuk.sf.net)
- 许可证:GPL
Edyuk 是另一个跨平台的集成开发环境,设计用于 Qt。Edyuk 是围绕透视图和插件构建的,它完全集成了设计器和 Qt Assistant,因此您可以在 Edyuk 环境中在代码视图和设计器之间切换。图 A-4 显示了显示代码透视图(顶部)和设计师透视图(底部)的屏幕截图。
项目文件支持很好,代码编辑器也是如此,但是打开项目可能会令人害怕,因为用户界面在加载时有时会没有响应。然而,开发速度很快(在我写这本书的时候),所以在你读到这本书的时候,这种情况可能已经改善了。
注意使用右下角的按钮可以显示或隐藏组成每个透视图的不同面板。这些按钮并不总是容易找到。
图 A-4。 行动中的 Edyuk 编辑
十八、附录 B:容器、类型和宏
Qt 提供了一系列宏、类型和容器,让开发人员的生活更加轻松。在比较和使用这些功能时,您可以将本章作为参考。
容器
有许多可用的容器,我把它们分成三组:序列、专用容器和关联容器。序列只是保存对象的普通列表。专用容器为保存某种内容类型或特定使用场景而优化。关联容器用于将每个数据项关联到一个键值。
以下每个部分都包含每种类型的优点和缺点—优点用加号(+)标出;弊标有减号()。
序列
QList
+开始时快速插入
+结尾快速插入
+快速索引访问
+快速迭代器访问
—在大型列表中间缓慢插入
QLinkedList
+开始时快速插入
+结尾快速插入
+在中间快速插入
+快速迭代器访问
—无索引访问
QVector
+结尾快速插入
+快速索引访问
+快速迭代器访问
+使用连续内存
开始时缓慢插入
—在中间缓慢插入
专用容器
QStringList
一个QStringList
是一个QList<QString>
,内置了字符串处理成员函数。下面的列表涵盖了其中的一些:
-
join
:将所有包含的字符串连接在一起,用给定的分隔符字符串分隔它们。 -
split
:使用给定的分隔符字符串将一个QString
拆分成一个QStringList
。这个方法是QString
类的成员。 -
replaceInStrings
:对所有包含的字符串执行搜索和替换操作。
QStack
一个QStack
是实现堆栈的列表。您使用push
方法将新项目放在堆栈的顶部。您可以使用top
方法查看顶部项目,也可以使用pop
方法获取顶部项目。
QQueue
一个QQueue
是实现队列的列表。您可以使用enqueue
方法将新项目放在队列的末尾。您使用dequeue
方法从队列的开始获取项目。您可以查看队列中的第一个项目,而不用使用head
方法将它从列表中删除。
QSet
集合是没有任何顺序或计数的键的集合。您可以使用insert
方法或<<
操作符插入新的键。然后,您可以使用contains
方法查看给定的键在集合中是否可用。要移除钥匙,使用remove
方法。
关联容器
关联容器将给定的键关联到一个值或一组值。哈希和映射的区别在于,哈希使用哈希函数对键进行排序,而映射保持键的顺序。哈希函数获取键值,并从中计算出一个称为哈希值的整数。结果是,散列可以更快地查找键,因为整数比较很快,而映射在遍历它们时更容易预测(因为它们根据键值而不是哈希值对内容进行排序)。
散列中使用的值和键必须是可赋值的(它们必须提供一个operator=
)。还必须有一个qHash
函数重载返回用作键的类型的uint
哈希值。
映射中使用的值和键必须是可赋值的,就像散列中使用的值和键一样。不是为键类型提供一个qHash
函数,而是必须有一个operator<
可用。
QHash
要将值插入到QHash
中,可以使用hash[ key ] = value
方法或调用insert( key, value )
方法。要确定散列是否包含给定的键,可以使用contains
方法。要获得给定键的值,使用value( key )
方法。
您可以使用keys
方法获得所有键的列表,使用values
方法获得所有值的列表。这两种方法都以任意顺序返回数据。通过一个QHashIterator
,你可以遍历散列中保存的所有键值对。
QMultiHash
QMultiHash
是为每个键分配几个值的散列。使用insert( key, value )
方法插入值。虽然键和值可以通过与使用QHash
相同的方法获得,但是通常使用values( key )
方法来获得与给定键相关的值的列表。
QMap/QMultiMap
QMap
和QMultiMap
的用法与QHash
和QMultiMap
完全相同。关联容器部分的介绍中描述了这些差异。
类型
Qt 提供了一系列以跨平台方式定义的类型。这意味着在所有平台上,无符号 16 位整数就是无符号 16 位整数。
Qt 还提供了一个 variant 对象,可以用来表示数据并在几种类型之间进行转换。
按大小分类
以下类型保证其内容的大小。通过在读写 Qt 流时使用它们,它们的字节序也可以跨平台边界保留。
-
quint8
:8 位无符号整数,范围 0–255 -
quint16
:16 位无符号整数,范围 0–65535 -
quint32
:32 位无符号整数,范围 0–4294967295 -
quint64
:64 位无符号整数,范围 0–1.844674407 e19 -
qint8
:8 位有符号整数,范围 128–127 -
qint16
:16 位有符号整数,范围 32768–32767 -
qint32
:32 位有符号整数,范围 2147483648–2147483647 -
qint64
:64 位有符号整数,范围为 9.223372036 e18–9.272036 e18
不保证它的大小,qreal
仍然有用,因为它在除 ARM 之外的所有平台上都代表一个double
值。在 ARM 平台上,类型代表一个float
,因为 ARM 在双精度上有性能问题。
变体类型
QVariant
类型可以用来保存 Qt 应用程序中使用的大多数值类型。当给一个QVariant
对象赋值时,该值会自动转换成一个QVariant
。要将一个QVariant
转换成给定的类型,您必须指定您期望的类型。QtCore
模块中所有可用的类型都可以通过使用to
类型方法进行转换,其中类型是类型名。这样支持的类型有bool
、QByteArray
、QChar
、QDate
、QDateTime
、double
、int
、QLine
、QLineF
、QList<QVariant>
、QLocale
、qlonglong
、QMap<QString, QVariant>
、QPoint
、QPointF
、QRect
、QRectF
、QRegExp
、QSize
、QSizeF
、QString
、QStringList
、QTime
、uint
、
在QtGui
模块中使用的大多数其他 Qt 类型也可以和QVariant
类一起使用。要将这样的类型转换成一个QVariant
,只需将它分配给QVariant
对象。要将它们从QVariant
转换,请使用value<type>
方法。
注意如果你用的是 MSVC 6.0,需要用qvariant_cast
而不是value<type>
。
使用变体支持自定义类型
为了支持您自己的类型与QVariant
类的组合,您需要将它注册为一个QMetaType
。你可以通过使用Q_DECLARE_METATYPE(type)
宏来完成。您可以将此宏与您的类一起放在头文件中。
为了能够在所有使用QVariant
类的情况下使用您的类,您需要通过调用qRegisterMetaType<type>( const char *typeName )
的函数调用来注册它。类型名应该是类的名称;例如:
qRegisterMetaType<MySpecialType>( "MySpecialType" );
您打算以这种方式使用的所有类型都必须支持不需要任何参数的公共构造器,以及公共复制构造器和公共析构函数。
宏和功能
Qt 附带了许多宏和函数,以方便的方式提供了常见的操作。函数和宏分为三个部分:值处理函数、随机数函数和宏迭代。
对待价值观
在处理值的时候,你经常会发现自己在寻找最大值、最小值等等。所有这些比较都可以作为函数使用:
-
qMin( a, b )
:返回a
和b
中的较小值。 -
qMax( a, b )
:返回a
和b
中的较大值。 -
qBound( min, v, max )
:如果在min
和max
之间,返回值v
;否则,小于min
则返回min
,大于max
则返回max
。如果min
大于max
,则结果未定义。
qAbs
函数用于查找给定参数的绝对值。
您可以使用qRound
和qRound64
函数将qreal
值四舍五入为整数。qRound
函数返回一个int
值,这意味着不同平台的结果可能不同,因为int
的大小可能不同。这个潜在的平台相关问题由qRound64
解决,因为它返回一个在所有平台上大小相同的qint64
值。
随机值
伪随机数通过qrand
和qsrand
函数处理。随机数只是伪随机的,因为相同的种子给出相同的数字序列。这意味着使用可变值作为种子非常重要。一个常用的值是当前系统时间。
qrand
函数返回数字序列中的下一个整数,而qsrand
用于播种序列。如果你想得到一个可预测的数字序列,确保在qrand
前使用qsrand
。
从qrand
返回的值属于int
类型。这意味着它的大小会因平台而异。限制给定随机数范围的一个简单方法是结合使用模数运算符和偏移量。例如,要生成一个介于 15 和 30 之间的随机数,可以使用下面一行代码:
int value = 15 + qrand()%16;
这段代码使用%16
操作创建一个 0 到 15 之间的随机数。然后加上 15,将范围移动到 15 到 30。
迭代
当遍历一个列表时,foreach( variable, container )
宏非常方便。该宏适用于所有 Qt 容器。例如,要迭代一个QStringList
,使用下面的代码行:
foreach( QString value, valueList ) doSomething( value );
当你想永远迭代的时候,通常使用空的for
循环(for(;;)..
)。)或者一个永恒的while
循环(while(true)..
)。).为了让你的代码更容易阅读,请使用forever
宏。下面一行显示了它在实践中的样子:
forever doSomething();
如果您不希望 Qt 将foreach
和forever
关键字添加到您的全局名称空间中,请将no_keywords
值添加到项目文件中的CONFIG
变量中。您仍然可以通过Q_FOREACH
名称使用foreach
宏。foreach
宏作为Q_FOREVER
可用。
第一部分:认识 Qt
在本书的前几章,你将熟悉 Qt 的工作方式——包括使用可用的类以及创建自己的类与现有的类交互。您还将了解构建系统和一些工具,这些工具有助于让 Qt 开发人员的生活更加轻松。
第二部分:Qt 积木
T 他的部分深入看 Qt 的关键部分。这里介绍的类和技术使您能够创建和修改 Qt 构建块,并为您自己的应用程序创建定制组件。