目录
一、Qt 是什么
- 是一个C++的第三方开发库,含开发用户界面的组件库;
- 是一个跨平台的库,兼容Windows、Linux、Mac等系统。
二、Qt 历史
Qt库历史悠久,超过30年的发展历史。经历曲折,跌宕起伏。至今仍然生机勃勃。
Qt 库最初由芬兰公司 Trolltech 开发,后来被瑞典公司 Digia 收购。Qt 最早是作为一个用于开发图形用户界面(GUI)的工具包出现的,但后来发展为一个跨平台的应用开发框架,提供了一系列的工具和类来帮助开发人员开发应用程序。现在,Qt 库在各种平台上都得到广泛使用,包括 Linux、Windows、macOS 和 Android。
时间 | 主角 | 事件 |
1991年 | 挪威的 Eirik Chambe-Eng 和 Haavard Nord | 初创开发的库 |
1994年3月 | 挪威的 Eirik Chambe-Eng 和 Haavard Nord | 成立奇趣科技公司(Trolltech)、商业授权 |
2000年 | 奇趣科技公司 | 发布 GPL(GNU General Public License)许可证的开源版本Qt |
2008年 | 诺基亚和奇趣科技公司 | 诺基亚公司收购了奇趣科技公司、增加了 LGPL(GNU Lesser General Public License)的授权模式 |
2011年3月 | 芬兰IT服务公司 Digia | Qt 商业授权业务出售给了芬兰IT服务公司 Digia |
2014年9月 | Digia宣布成立 Qt Company 全资子公司 | 独立运营 Qt 商业授权业务。目前 Qt 公司大力推广移动平台开发和商业应用 |
三、Qt 授权
它提供了两种授权方式:商业授权和开源授权。LGPL 和 GPL 是免费发布,商业版则需收取授权费。
-
Qt 商业版授权适用于开发专属和/或商业软件。这个版本适合那些不希望与他人共享源代码,或者遵循 GNU LGPL 2.1 或 GNU GPL 3.0 版本条款的开发人员。它提供了技术支持服务,允许开发人员修改 Qt 的源代码,而无需公开。
Qt 4.5.0 及更高版本遵循 GNU LGPL。LGPL 允许任何许可证的软件链接到它,并允许专属软件作为类库引用、发布和销售。您可以购买支持服务。
如果您希望将 Qt 应用程序与遵循 GNU GPL 3.0 版本条款的软件一起使用,或者您希望 Qt 应用程序遵循该许可证的条款,则这个版本的 Qt 库适合开发这类应用程序。您也可以购买支持服务。
四、Qt适用领域
Qt适用开发桌面程序、移动端的App。另外,Qt可以网站服务器开发吗?从技术上来说,是可以的,但是有更多更好的技术可选择,不推荐用Qt开发服务器端。
五、C++的标准库
首选C++是有官方标准库的。但是标准库并不友好,使用过程中存在类似以下的感受:
- 功能不够完善,比如字符串string类没有劈开字符串的方法、没有string转wstring的方法,没有trim方法、没有忽略字符串大小写比较的方法等等。而这些在日常的开发中,经常用到,如果没有,你得自己去实现或者找一个其他的库;
- 功能接口的调用过于繁琐,往往望而生畏的感觉。
- 也许对于不同的人还有不同的感受,比如方法名有很多下划线,看起来眼花缭乱。
对C++标准库的感受,这里不一一列举。毕竟,不同人感受不同。如果您的项目必须要用C++的标准库,也是可以的,Google的Chrome就是大量使用标准库,并且还拓展了标准库,把拓展的部分开源出来供大家使用。所以,如果项目必须使用标准库,可以考虑使用Google的开源C++库:Abseil 作为补充。
除了标准库,C++还有一些类似标准库的第三方库,举例子如下:
库名 | 简介 |
Boost | C++标准委员会库工作组成员发起,在C++社区中影响甚大,其成员已近2000人。 但是没有提供图像界面的开发库。 这个库非常庞大,有很多子库,子库目录非常值得去浏览一遍。说不定哪天还真的用得上。 |
Qt | 就是本文的主角了。在我看来,如果Qt作为C++官方标准库,那么C++将会像Java一样完善好用。 Qt的子库非常多,很多Boost里面有的库,在Qt也有类似的库或功能。并且还提供完善的跨平台的图像界面库。 Qt的类、方法设计也是下足了心思,让开发者使用起来非常舒服。下面会讲到它的优点。 |
JUCE | JUCE (Jules' Utility Class Extensions)是由Raw MaterialSoftware发布的一套基于c++的跨平台应用程序框架类库(Windows, Mac,Linux)。JUCE的特殊之处在于其友好的用户界面以及强大的音频、图像处理能力。JUCE适合那些想使用干净、快捷、高层的API,而不想 把时间浪费在使用不同类库,面向不同平台上的开发者。JUCE能够胜任大型、复杂的应用程序(C++)的开发。 |
能够担当标准库的第三方库,确实不多,想进一步挖掘更多库的读者,可以到百度、Google等引擎去搜索和了解。
六、为什么选Qt
类比Java, 就会非常明显感受到Java的官方标准库非常完善,涉及到日常软件开发的方方面面。既可以开发桌面程序也可以开发网站。并且有活跃的开源社区,数量庞大的开源项目,成熟完善的工具链。让Java开发工程师如鱼得水。
但这里讲的是C++,咱C++木有这样的官方库。而Qt库相比其他的库,拥有完善的基础类库和图形界面库,并且拥有跨平台特性,更像是大多数应用软件开发者所期望的C++标准库。
Qt的核心能力在于基础类库、用户图形界面库、跨平台特性。除此之外,它的开源、库完整性、稳定性、易用性、代码美观程度、完善的帮助文档、搜索引擎可查到的资料、免费商用、与时俱进的版本更新等等,都在为它加分。
作为直观对比,拿Qt、C++标准库、Boost来实现几个小逻辑,这些小逻辑可能在开发日常经常用到,视不同项目而不同:
1、获取当前时间的毫秒数
C++标准库
#include <chrono>
using namespace std;
long long getCurrentMillisecond(){
auto time_now = chrono::system_clock::now();
auto duration_in_ms = chrono::duration_cast<chrono::milliseconds>(time_now.time_since_epoch());
return duration_in_ms.count();
}
Boost 库
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
long long getCurrentMillisecond(){
ptime epoch(date(1970, boost::gregorian::Jan, 1));
time_duration time_from_epoch = second_clock::universal_time() - epoch;
return time_from_epoch.total_milliseconds();
}
Qt库
#include <QDateTime>
long long getCurrentMillisecond(){
return QDateTime::currentMSecsSinceEpoch();
}
单从代码行数,心智负担来看,Qt库的实现,是比较人性化的。它单纯提供一个方法来完成该逻辑。
2、字符串劈开
给定一个字符串“Leander#GuangDong#100”,需要劈开该字符串到一个数组或者字符串列表均可。
C++标准库
不支持该方法,需要自行实现。经过一番折腾,实现如下
#include <string>
#include <sstream>
#include <vector>
using namespace std;
vector<string> split(const string &s, char delim) {
stringstream ss(s);
string item;
vector<string> elems;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
Boost 库
#include <string>
#include <vector>
using namespace std;
#include <boost/format.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
vector<string> split(const string &s, char delim) {
vector<string> elems;
boost::split(elems, s, boost::is_any_of(delim));
return elems;
}
Qt库
#include <QString>
#include <QStringList>
QStringList split(const QString &s, char delim) {
return s.split(delim, QString::SkipEmptyParts);
}
除此之外,QString还提供9个split的方法,方便您随意劈,如下:
普通的使用场景下:
QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QStringList split(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QStringList split(const QRegExp &rx, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
QStringList split(const QRegularExpression &re, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
在性能要求苛刻的场景下:
QVector<QStringRef> splitRef(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QVector<QStringRef> splitRef(QChar sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QVector<QStringRef> splitRef(QChar sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QVector<QStringRef> splitRef(const QRegExp &rx, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
QVector<QStringRef> splitRef(const QRegularExpression &re, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const
3、忽略大小写的字符串比较
C++标准库
#include <algorithm>
#include <cctype>
#include <cstring>
#include <iostream>
using namespace std;
bool iequals(const std::string& str1Input, const std::string& str2Input)
{
string str1 = str1Input;
string str2 = str2Input;
transform(str1.begin(), str1.end(), str1.begin(), ::toupper);
transform(str2.begin(), str2.end(), str2.begin(), ::toupper);
return strcmp(str1.c_str(), str2.c_str()) == 0 ? true : false;
}
Boost库
#include <boost/algorithm/string.hpp>
#include <string>
bool iequals(const std::string& str1Input, const std::string& str2Input)
{
return boost::iequals(str1, str2);
}
Qt库
#include <QString>
bool iequals(const QString& str1Input, const QString& str2Input)
{
return str1Input.compare(str2Input, Qt::CaseInsensitive) == 0; // equal will be true
}
更多的就不一一列举,读者可自行去了解更多。从上面的几个例子,可以明显感受到:C++标准库的使用体验是最槽糕的,boost好一些,Qt感觉良好。
在此建议,选择好的库,就像选择好的伙伴一样重要。一路开发下来,会顺畅很多,后期发布运行也更稳定。