首页 Qt 学习之路 2 Qt 学习之路 2(1):序

Qt 学习之路 2(1):序

110 9.9K

51CTO 上面曾经有过这么一个系列,具体是 Qt 的入门教程。当时强调过,那些文章大致是根据 《C++ GUI Programming with Qt 4, 2nd Editon》编写的。时过境迁,现在回头看看,已经过去了整整三年。如果你仔细看下那篇系列文章就会发现,发表时间竟然是 2009 年 8 月 20 日;而今天是 2012 年 8 月 20 日。或者是冥冥之中的感觉,竟然选择了同一个时间。

现在,按照年前做过的计划,我会来履行我的承诺,重新修订《Qt 学习之路》。不过,豆子计划将其取名为《Qt学习之路2》,或者就当作是 2.0 版本吧!

从网上的反应来看,这个系列的文章获得了很多读者的认可。时间已经过去三年,Qt 的发展也有了翻天覆地的变化。如果不受出售事件的影响,Qt 5 即将在 2012 年 9 月发布。而现在,最新代码库里面已经有了 beta。这意味着,Qt 5 的特性已经确定,不会再有大的改变。所以,我觉得,我已经可以着手进行一次修订。

本次修订的原则是,结构上大致保持前一版本的顺序不变,包括基本知识的介绍、常用 GUI 组件的介绍、常用技术的介绍等;内容上将结合 Qt 4 与 Qt 5 两个部分。在可以预见的未来,Qt 4 的程序,无论从旧代码的维护,还是新的程序的出现,都不会立刻退出历史舞台。Qt 5 也并不像 Qt 4 与 Qt 3 的升级那样的激烈,因此,我觉得有必要同时介绍这两个版本。当然,我并不确定这种“同时”会不会一直持续到系列的最末,因为也有可能 Qt 5 以一种摧枯拉朽之势,将 Qt 4 扫出历史舞台。这一切尚未可知。鉴于此,豆子才不将本系列命名为《Qt 5 学习之路》,而是以第二版称呼。

另外,对于上一版本,豆子还是很内疚的。因为并不是一个完整的介绍,Qt 的很多优秀特性,比如 XML,比如数据库,比如网络,都没有进行介绍。这主要是因为当时接触 Qt 也并不是很多,很多特性没有使用过,即便抄书写出来,也会觉得心里没底。现在豆子对 Qt 了解更多,所以,在这次修订中,豆子将竭尽全力将一些用到的特性介绍一下。

至于本系列的定位,豆子主张将其定位于入门教程。不过,如果可能的话,豆子希望能够在其中穿插一些有关 Qt 实现的相关内容。这部分内容肯定不会是基础的,比如信号槽的实现等。不过,对于这一点豆子也不敢肯定,毕竟要接触到实现层面上的东西,总要花费一定时间和精力的。

这次修订,没有了《C++ GUI Programming with Qt 4》这本书作为提纲,一切都将按照自己的思路来。豆子将尽量跟随这本书的顺序,同时希望能够按照 Qt 5 的思路,按照模块来介绍 Qt。当然,作为修订版,本次修订的着重点在于 Qt 5,Qt 4 的内容将追随 Qt 5 进行介绍。同前文一样,本系列也会参考《C++ GUI Programming with Qt 4》一书,不过鉴于本书的某些自认为不合适的组织(比如以一个过大的项目作为示例),本版更多会直接参考 Qt 文档。很多原理性内容,可能会直接来源于文档,所以,感兴趣的朋友建议直接翻阅文档,以文档原文为准。

说了这么多,总之就是,尽量完成一篇相对高质量的教程。如果有任何建议或者意见,欢迎给豆子留言。

以此,是为序。

110 评论

Anonymous 2012年8月20日 - 14:32

真不是吹捧……但我无以言表我对阁下的赞许。QT5是一个伟大的框架,底层的兼容和抽象封装一定相当困难,这就注定了短时期内根本不会有替代者,java的ui毫无体验性,cairo等等只是绘制没有toolkit,opengl只是规定。完整的跨平台甚至可以跨上移动端的gui框架,如今只有qt,在商业市场是遇到重重障碍,但终究这货携带着次世代的标准算是产出来了。这个系列是qt中文圈(尤其是qt5亦即尤指cutting edge性)是绝无仅有的,所以多谢了。

回复
DevBean 2012年8月20日 - 14:55

阁下赞言真是热情洋溢啊……无以为报,只有努力了!

回复
精英王子 2012年8月23日 - 00:56

支持...

回复
lzihua 2012年8月24日 - 20:19

支持下,加油! 😀

回复
liuyanghejerry 2012年8月26日 - 20:43

其实Qt5这么一折腾,就连原先熟悉Qt的人也得考虑好好再重新认识一下Qt了。中文圈子里Qt5的资料不多,支持下LZ。

回复
DevBean 2012年8月26日 - 23:00

这个也就是个见仁见智的问题了。毕竟是大版本的升级,也不可能很小的改变。

回复
frogoscar 2012年8月31日 - 04:33

大力支持,不得不支持!
哈哈,您的Qt学习之路(-)我就很喜欢,以前也看的。
期待您的又一力作,辛苦了。

回复
DevBean 2012年8月31日 - 08:01

多谢多谢!

回复
大米 2012年9月1日 - 21:13

严重支持。。。一直关注这您的文章。这次又有大作问世了。期待。

回复
DevBean 2012年9月1日 - 21:15

谢谢支持哦

回复
langziyang 2012年9月13日 - 16:57

什么都不说了,看你是一就觉得很不错,然后在群里你也经常指导我这个新手,感谢!

回复
DevBean 2012年9月13日 - 18:55

过奖过奖

回复
strak47 2012年9月29日 - 00:12

😛 支持支持~正在阅读你之前版本的QT学习之路,很有帮助哦 😆 😉

回复
DevBean 2012年9月29日 - 10:44

感谢支持!这个版本和之前版本的有些重复,讲解也详细得多,可以以此为主的

回复
good 2012年9月29日 - 13:14

支持LZ.
或许留言的人不多,不过看你教程的人可不少,因为内容浅显而懂.很适合新手学习.
而不像那些学术派写的书,实在不明白他们写书到底是为了传授知识还是为了彰显自己的知识!!!

回复
DevBean 2012年9月29日 - 13:24

过奖了哦

回复
great 2012年10月12日 - 20:20

支持,我就是看第一版学会的Qt 😀

回复
DevBean 2012年10月13日 - 09:03

感谢支持哦~

回复
豆豆 2015年1月9日 - 14:27

你好,最近正在学这个,能给我一份电子稿吗,上学的研究所是保密单位,不能带电子器材进所里,想把它打印出来。

回复
风神 2012年11月13日 - 14:56

支持,我现在正在看第一版,真的很易懂。其实很久之前就加到收藏夹了,最近才开始看。因为我用的是诺基亚手机,上面没有复读机,我想自己写一个,所以想学QT,呵呵。

回复
DevBean 2012年11月14日 - 10:14

加油哦!

回复
风神 2012年11月19日 - 17:26

今天已经把QT学习之路1看完了,呵呵。感谢你的奉献。

回复
DevBean 2012年11月19日 - 19:21

感谢支持~

回复
马恒 2015年1月19日 - 16:24

大神 我是新手求罩, 弱弱的问下 哪个群?

回复
Jeffrey Lee 2012年12月27日 - 08:37

非常棒,原创Qt学习文档,第一次见到,Qt将会越做越好,大家一起努力吧!

回复
andmoe 2013年1月15日 - 15:09

泪流满面==

回复
JiaPan 2013年1月30日 - 18:34

你好,我写好的程序在QT里编译运行没有问题,可是为什么直接运行生成的exe文件就无法运行呢?提示:无法启动此程序,因为计算机中丢失 Qt5Widgets.dll。尝试重新安装该程序以解决此问题。 这是为什么呢? debug和release都试过了。

回复
豆子 2013年1月31日 - 15:42

那是因为没有找到所需的 dll,只需要把 dll 所在目录加入系统路径,或者把 dll 复制到 exe 同一目录下即可(后者也是发布动态链接的 Qt 程序时所需要做的)。

回复
JiaPan 2013年1月31日 - 20:10

我看了下,把所需的dll放进去一共30多MB,如果我想把自己写好的小程序分享给别人,就拿那个简单的记事本来说,总不能给人家发个30多M的压缩文件过去吧。

回复
豆子 2013年2月5日 - 15:09

release 版本的 dll 一般不会那么大。不过如果你添加了很多组件,比如 webkit 之类就可能更大。这也是不可避免的,你在使用 MFC 的时候不也是要安装 VC 重分发包嘛。如果实在太大,可以考虑使用 ASPack 之类的压缩文件压缩下,体积能小一些。

回复
great 2013年2月5日 - 17:24

如果一定要小最好自己编译Qt源代码 QtCore需要icu 会带上一堆dll 自己编译不给icu这一堆dll就不需要了 类似的还有angle

xiechunhui 2013年3月27日 - 17:11

豆子你好,请问Qt里有自带的打开txt和pdf等文档的命令么? 实现商业软件中点击Help按钮,弹出帮助文档的功能。多谢!

回复
豆子 2013年3月27日 - 18:07

不知道你的需求是什么,如果是要使用第三方软件,需要调用系统安装的程序打开,否则的话你要自己读取文档,然后写一个简单的帮助浏览器。另外,你可以看看 Qt Help 模块,也就是 Qt 自己的帮助系统。

回复
Rui-huai Zhang 2013年4月22日 - 16:05

非常好的原创系列文章,打算把这教程啃下来! 😛

回复
信相一号 2013年5月19日 - 10:20

本人只学过C语言,没有学过C++,我想问一下豆子,如果想学Qt,是否可以Qt和C++同步学,还是最好先学 C++,再学Qt? 谢谢!

回复
豆子 2013年5月20日 - 09:34

最好先学 C++,因为 Qt 是 C++ 的库,如果不会 C++,很多 Qt 代码也是看不懂的。

回复
信相一号 2013年6月8日 - 09:52

请问豆子,学Qt需要学习数据结构和算法的相关课程吗?听说要学好编程,必学数据结构和算法,谢谢。

回复
半夏 2013年5月24日 - 21:59

豆子,在看您《Qt学习之路2》遇到了问题。您在20章事件中提到bool CustomTextEdit ::event (QEvent *e) 的函数(69页)。于是我新建customTextEdit类(用public方式继承了QTextEdit类),并添加protected: bool vent(QEvent *e); 最后在main()函数中调用 customTextEdit *textEdit = new customTextEdit(&w);发现出来的编辑框无法操作,请问您能抽空指点下吗?非常感谢。
--忠实的读者

回复
豆子 2013年5月24日 - 22:05

如果是 https://www.devbean.net/2012/10/qt-study-road-2-event-func/ 这里的 bool CustomTextEdit::event(QEvent *e) 这段代码,我已经在后面添加了说明,由于没有调用父类的 QTextEdit::event() 才会导致这一问题。这段代码本意就是提醒注意不要忘记调用父类的同名函数。

回复
半夏 2013年5月24日 - 22:18

哦。我终于明白了。还要加上类似于Init()函数去调用父类同名函数吧?哈哈,谢谢豆子大哥。真的很感谢您跟您的教材。

回复
半夏 2013年5月25日 - 08:08

return QTextEdit::event(e);是父类的这个事件没加的原因吧。 😛

回复
豆子 2013年5月25日 - 11:23

是的哦,就是这个原因的

回复
特地来支持豆子 2013年6月7日 - 00:19

楼主的精神很值得我们学习 谢谢你给我们新手写出教程

回复
打不倒的小龙龙 2013年9月18日 - 10:35

学生表示对您无尽的感谢,,这个系列的文章对我qt入门真的起了很有作用。继续关注,继续支持。

回复
豆子 2013年9月18日 - 14:18

感谢支持!

回复
SimpleXY 2013年11月15日 - 20:42

博主加油~

回复
豆子 2013年11月15日 - 21:32

谢谢~

回复
kang 2013年11月23日 - 18:19

不久前才开始学学习QT,从豆子空间一路跟了过来,从09开始到现在持续到现在,心中对博主满满的敬意啊。支持。

回复
豆子 2013年11月23日 - 21:06

感谢支持!

回复
曾晨 2013年12月29日 - 17:42

你好 , 我Qt的初学者 , 我在官网下载Qt时感觉很迷茫 , 不知道要下载哪个, 麻烦你写他们之间的不同点:
Qt 5.2.0 for Windows 32-bit (MinGW 4.8, OpenGL, 689 MB)
Qt 5.2.0 for Windows 32-bit (VS 2010, 570 MB) 、
Qt 5.2.0 for Windows 32-bit (VS 2010, OpenGL, 569 MB)、
Qt 5.2.0 for Windows 32-bit (VS 2012, 579 MB)

回复
豆子 2013年12月29日 - 21:04

这四个首先是编译器的区别:第一个是MinGW;第二、三个是VS2010;第四个是VS2012。标记有OpenGL的含义是使用OpenGL后端;否则的话使用ANGLE后端。ANGLE是Google发起的一个开源项目,旨在将OpenGL ES 2.0 API映射到DirectX 9 API。如果你的应用程序使用了不包含在OpenGL ES中的OpenGL API;或者需要运行在Windows XP平台,那么需要选择OpenGL版本;否则的话,如果不想要求用户安装最新的显卡驱动,需要使用QtMultimedia模块的回放功能,就要选择ANGLE版本。

回复
rrrdr 2014年4月10日 - 09:40

你好,我想问一下,就现在的qt5来看,qt用的是哪一版本的angel?而angle现在发展得怎么样?是否全面做好OpenGL ES 2.0 API映射到D9足够完善?angel难道不支持d9?

回复
豆子 2014年4月11日 - 10:25

关于 ANGLE 不了解,不便过多评论 ;-P

回复
yys 2013年12月30日 - 08:52

初学QT,感谢大大无私奉献

回复
worldsing 2013年12月31日 - 22:27

《qt学习之一》大部分看了

回复
若繁 2014年1月13日 - 13:25

真是非常感谢博主对于Qt的简单而又详细的介绍,最近公司做开发,需要学习一些Qt的知识,能够读到博主的文章,真是受益匪浅

回复
飞檐走壁 2014年1月16日 - 16:51

不错

回复
yuexuan218 2014年1月25日 - 22:34

大神的文章必须支持!!!

回复
壹号 2014年3月15日 - 22:39

请问一下,第一版和第二版的区别是?

回复
豆子 2014年3月17日 - 09:12

第一版使用的是 Qt 4,第二版在第一版的基础上进行修订,主要增加了最新的 Qt 5 的内容。

回复
insaneguy 2014年4月9日 - 17:03

感谢博主,刚发现有第二版,支持!

回复
豆子 2014年4月11日 - 09:18

感谢支持!

回复
oxy 2014年4月25日 - 21:20

QtCreator 在Debug下构建总会出现“LNK1123: 转换到 COFF 期间失败: 文件无效或损坏”,请问该怎么解决呢?谢谢

回复
豆子 2014年4月28日 - 10:21

这个问题我也遇到过,原因是cvtres.exe版本过多。搜索cvtres.exe,如果发现多个文件,使用最新的替换老的文件就可以了。替换之前记得备份一下。

回复
ding 2014年5月22日 - 11:02

开始看了,由于只有C基础,和一点php对象基础,现在边看c++类方面的边看您写的qt2
,有点费力,半天看一点,还只看了几页,建议作者多写点代码注释,方便读者阅读。

回复
豆子 2014年5月23日 - 14:43

好的,以后注意!因为大部分代码都是在文章中解释的,所以一般都没有注释。另外,按照你的说法,你的问题更多可能是面向对象或者 C++ 语法方面的困难,这点在本系列文章中也不大好再加注释。

回复
ding 2014年5月22日 - 11:53

Newspaper(const QString &name) ://引用基类的对象,定义函数并传参
m_name(name)
{
}
注释按自己理解写的,m_name(name)这个函数没有表达式,使用返回值吗,后面又把m_name当作参数传给一个函数,不解意思啊。这个自定义信号槽的的例子都看了2两天。看不懂,

回复
豆子 2014年5月23日 - 14:44

m_name(name) 是 C++ 初始化参数列表的写法,不是函数调用。你应该去看看 C++ 基础。

回复
xuan120520 2014年5月23日 - 22:24

楼主,您好!我是QT的初学者,我在网上搜到您的文章,看过后,真心佩服啊!我想咨询下,我之前没学过C++,前几天才看完,现在需要学习QT4迫在眉睫,我看到您的《QT学习之路》有两个版本,我想请问下,以我的这个基础,是学习您的《QT学习之路》第一个版本还是第二个版本比较好了?非常谢谢啊,期待楼主的解答!

回复
豆子 2014年5月27日 - 09:17

第一个版本是 Qt 4 的,第二个版本涵盖了 Qt 4 和 Qt 5。建议直接看第二个版本就可以了,基本是完全覆盖了第一版的。或者二者结合起来,第二版为主,第一版为辅。

回复
xuan120520 2014年5月27日 - 09:43

好的,谢谢豆子。已经在看了,觉得写得非常好,看您的文章比我看这本《精通Qt4编程》容易懂的多,而且也有兴趣很多,非常感谢豆子为我们提供这么好的文章。

回复
黑夜风袭 2014年8月10日 - 08:37

感谢作者!初学Qt,帮助很大!

回复
豆子 2014年8月10日 - 13:43

感谢支持

回复
马波 2014年8月27日 - 13:15

豆子大哥,我是在51CTO上面看到你的精品博客的,尤其看到你那个对源码的分析,可是怎么对源码的分析后面没有了呢?是转移到别的地方去了吗?

回复
豆子 2014年8月27日 - 20:15

这部分还没有继续下去,目前还只有那部分分析。

回复
马波 2014年8月28日 - 13:08

奥,那这个还有计划继续吗?网上这方面资料好少。看不懂,有什么途径吗?

回复
豆子 2014年9月2日 - 09:30

如果有兴趣,就只能自己先研究下源代码。毕竟网上的东西也会过时,随着 Qt 的发展,其源代码也在不断进化。

回复
Never 2014年8月29日 - 14:18

感激之情,无言以表。

回复
huge 2014年10月21日 - 15:07

好好学习,天天向上。

回复
moonlqer 2014年11月18日 - 19:22

我也是Qt深度入迷用户,我用Qt做嵌入式方向的移植,看了博主的文章,觉得博主一定是qt高手,希望以后多探讨些问题。

回复
豆子 2014年11月19日 - 10:27

欢迎讨论,一起学习!

回复
moonlqer 2014年11月19日 - 17:01

豆哥,问你个问题:
QGraphicsView 类中,使用paint接口绘制文字的时候,painter.setPointSize()函数失效,不论怎么设置,得到的字体大小都没有变化,你遇到过这种情况么?

回复
Daniel 2015年1月30日 - 20:53

你好,现在Qt依然是跨平台,做界面最好的开发工具吗?还有没有别的可推荐的?另外Qt开发Android的app是不是鸡肋功能?还是也可以做出兼容性,体验很好的app?

回复
豆子 2015年2月3日 - 09:24

目前移动端的体验个人认为并不好,Android 方面不是很了解,但是 iOS 的表现并不非常理想,主要原因在于 Qt 在 iOS 的控件表现并不是 iOS 原生样式,而是类似 win32 那种样式,这样与平台不一致的表现是不会通过 App Store 的审核的(当然,你可以自己实现样式,或是其它方案,但这样的工作量无疑很大)。目前还不了解是否有体验很好、具备实际应用价值的 app。至于桌面,Qt 的表现应该还不错,比起 gtk 和 wxWidgets 这类纯社区驱动的库,Qt 的商业支持也会加不少分。移动端跨平台,现阶段不妨考虑下 PhoneGap 之类的,可能会有更好的表现。不过按照 Qt 现在的发展势头,有可能会在未来时间做到更好的支持。

回复
Daniel 2015年2月3日 - 10:55

谢谢豆子的解惑,非常感谢。

回复
箭头向下 2015年3月11日 - 16:24

您好,请教一个问题。
我在Qt中有一个项目,包含了3个子项目,其中有两个子项目是app,一个是lib库,能不能将所有的qrc资源放入lib库中,然后在两个app中调用资源呢。如果可以的话是怎么实现的呢?
主要是因为两个app需要用到公用的qrc文件中的样式表文件方便统一UI。

回复
豆子 2015年3月12日 - 10:08

如果没有理解错误的话,应该是可以的。做法是,将整个 app 的 pro 文件的 TEMPLATE 设置为 subdirs,CONFIG += orders,SUBDIRS 按照需要的编译顺序添加:lib、app1、app2。然后在 app1 和 app2 的 pro 文件中加入 LIBS += ../lib (注意按需修改路径) 即可。可以参考下 Qt Creator 的源代码设计,以及 https://www.devbean.net/2012/01/a-qt-pro-design-method/ 这篇文章。

回复
箭头向下 2015年3月12日 - 10:28

恩,昨天已经差不多就是这个思路实现了,其实主要的就是qrc文件的加载。一定要在每个app中添加qrc文件位置。我使用pri文件配置解决了。谢谢啦。
不过还有个问题就是每个app都会将这个qrc打包一次...加大了app的体积和内存使用

回复
magichan 2015年4月18日 - 20:51

感谢,等我看完了
一定会扫二维码的

回复
小土豆海盗 2015年7月9日 - 15:21

已扫码支持楼主,楼主真心给力,刚开始看,看完后会继续扫描的~~

回复
柠檬 2015年8月31日 - 22:42

我刚接触QT的,DevBean的QT学习之路2 新手更容易学习QT,佳作! 但是“下一篇”的按钮在哪里呢,看完一篇后,想在下面点第二章的链接却找不到。。

回复
马恒 2015年9月1日 - 13:59 回复
豆子 2015年9月1日 - 17:36

因为使用的第三方主题,已经和主题提供商联系过了。现在先用插件替代一下,由于缓存的问题,可能需要一段时间才能出现在页面上。不便之处敬请谅解!

回复
jieziww 2015年10月6日 - 17:24

太棒了!!

回复
Qt菜鸟 2016年7月14日 - 16:06

豆子老师,请教个问题,Qt在视频窗体上面实现半透明效果的控件叠加。我用的VLC的开源库做了视频的播放(播放器嵌入到窗口的)。然后我想在视频界面是哪个天界透明的控件,比如label控件。我如果直接设置label位透明,他会把视频覆盖住,请问可有好的解决办法此(此问题网上没有找到好的解决办法,所以有偿解决)。这是我邮箱zhao_yi_huan@163.com。谢谢

回复
ccppaa 2016年8月29日 - 15:58

大神,qt打印如果设置微软雅黑字体的话,打包后在别的电脑上能正常使用吗

回复
豆子 2016年8月30日 - 09:26

这个我没有试过,不过如果对方电脑上面没有安装微软雅黑的话,应该是不可以的,除非你把微软雅黑与你的程序一起发布(注意协议问题)。

回复
徐晓晓 2017年3月25日 - 17:54

辛苦了,豆子。

回复
Walter 2019年7月8日 - 15:22

给力!

回复
Mie1P 2020年3月16日 - 11:56

豆子大大,我想问下,相比利用QT design设计界面,直接用代码设计界面有什么优势吗?我看您的教程里都是直接代码实现界面的

回复
豆子 2020年4月21日 - 13:26

直接设计比较快,不过我只是习惯用代码写界面,感觉会比 Qt Designer 更好控制

回复
冲锋的羊陀 2020年4月9日 - 15:39

在canpool上看到的学习之路链接,qml第二版的书买了也还没看的,又可以愉快的跟着走一段路了,开心

回复
林子渊 2020年11月28日 - 22:33

考古

回复
Nullbody 2021年2月20日 - 13:59

Qt6发布了,考虑更新一下吗?

回复
豆子 2021年2月23日 - 17:21

Qt6 与 Qt5 基本一致,但是目前阶段,Qt6 的模块有些缺失,以后会再考虑更新一下吧

回复
廖迪 2021年8月13日 - 16:28

现在已经是21年8月份了,从作者写文章,已经经历了好多事情了,哈哈哈,感觉好有趣啊 ,穿越时空的阅读一样。谢谢作者的分享。我是来自21年的新手菜鸟。

回复
缘起 2022年1月6日 - 16:41

2022年1月伊始,来打卡看看有没有QML相关的学习,时光荏苒呀 哈哈

回复
奇纳吉 2022年12月8日 - 21:34

2022.12.08,哈哈 马上就是2023一年 新年快乐

回复
码头薯条鸽子 2023年8月3日 - 11:17

2013.8.3初学QT,感谢豆子大大

回复
码头薯条鸽子 2023年8月3日 - 11:18

2023哈哈

回复

回复 strak47 取消回复

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2