最近在做CG的project,需要调用画点函数画出一些图元、生成真实场景。所以把学了一半的Qt拿出来继续学。

大三就开始断断续续的接触的一些Qt的东西,大四学了一点,但是没学懂。这次终于把Qt的一些机制搞懂了一点,把CG大作业制作过程记录下来,同时也作为简单的Qt入门。

老规矩,大神请绕道。

 

一.写在前面

  说实话,Qt真的不算难,上手本来应该挺快的(如果你故意忽略一些次要紧的概念,比如QOBJECT是啥,Qt的class结构长什么样子,UI工具怎么用。。事实上我也打算在这里这么做)。我的原则就是:咱们先把demo跑起来,Qt一些好的特性可以留着慢慢品味。

  Qt的安装比较麻烦,加上vs的问题,所以不是特别推荐在windows上面做。环境问题我们最后再谈,没有装环境的同学可以先看最后一节。

  此外给一些建议:学习Qt手边请备一本C++ primer,随时查阅;别纠结细节;找个QQ群,会有很多高手给你解决问题;找开源社区。

  市面上有一些Qt的书籍,大多是味同嚼蜡,翻开书就直接淹没在代码和设计细节的海洋里了,学起来真个痛苦不堪。我想了很久,终于想通了问题所在——设计GUI其实是个搭积木的过程,把各种图片和部件组合起来。但是教材太死板,把积木玩成了拼图,教你做个文本编辑器保证你做不出画板来。

  这里我给出最基本的概念和技巧,看完就可以直接写简单的Qt程序,实现你的想法(而不是教程的或者是我的想法)。

  OK,let‘s go

 

二.Qt部件和布局

    关于布局详细的可以看这里。但是我不准备在这里讲怎么布局。

  曾经我纠结了很久,觉得Qt好呆板,所有的教程都会教:用布局管理器,然后把布局管理器放到主要部件里面去。我一看到这种教程就要发疯:特么的这简直就是戴着脚镣跳舞。

  后来发现错了——Qt的部件处理非常自由。言归正传,先解释什么叫部件:

qt 与 机器学习 qt应该怎么学_Qt

上图就是两个部件,大的部件是Qwidget,小的为行文本框。所谓部件,又叫做窗口部件(widget),可以简单理解为窗口界面。习惯上我们把顶级部件称为窗口,把子部件成为部件。所有的部件都继承自Qwidget类。最常用的部件有主程序窗口(QMainWindow)、对话框(QDialog)、窗口部件(Qwidget,就是基类)。

  上图中的widget我们成为父部件,文本框成为子部件,显然父部件与子部件就是包含关系。

  每一个Qwidget极其子类对象都提供了绘制自己和用户交互功能(即监控各类事件)。

  每一个部件都可以放到别的部件里面去,也可以作为顶级部件,以窗口形式出现,这一点很赞——而且并不需要用布局管理器,只需要将子部件的父部件设置一下:

  son.setparent(father);

  这里 father 和 son是两个部件。这样设置了以后,son就被粘贴到了父部件里面。

  想象一下你是怎么做剪纸手工的:

    剪一个图案,一个双喜,一个方块。。。然后贴到纸面上。

   这个过程换成代码:

Qwidget father;
Qwidget son(father);

 是不是很直观?明白了父部件和子部件是如何嵌套设置的,你就可以随意画出你想要的部件,就像做剪纸手工一样。

  什么?不知道怎么做对话框?RTFM......

三.信号与槽

  这是Qt最让人爽的一部分,有句话叫做“前人之述备矣”。这里我整理出我理解的要点:

  所谓信号,实际上你可以从字面理解。某个按钮C被点击了,就会大喊:非礼。。啊不,是“我被点击了”。当然其他的部件是无动于衷的,但是某个特殊的B部件看见了就会对此作出反应。B部件特殊就特殊在:它的槽和c的信号是绑定在一起的。

  所谓槽就是接受信号的函数。根据信号槽可以作出一系列反应。下面是例子:

class C 
{
signals:
        void Help_C(int money);
.........
.........
};

class B
{
private slots:
        void B_Lend_C(int money);
.........
.........
};

C *PoorC;
B *RichB;

connect(PoorC,Help_C(int),RichB,B_Lend_C(int))

 signals和slots是Qt定义的两个关键字(不是c++的)。

  看上面的一段代码:

  首先在C类中定义了一个信号——Help_C,在B类中定义了一个私有信号(信号也可以是公有的)。在外部,定义了一个C指针PoorC和B类指针RichB。

  最重要的是最后一句:connect,把c的信号和b的槽连接起来,这样下次C大喊的时候B就知道要借钱给他了。

  多讲一句:信号和槽的变量需要一致,允许信号的变量比槽多。这是因为信号需要给槽传递数据(比如C需要多少钱?)上面的例子里面,我们通过一个int来传递数据。如果信号的变量比槽多,多余的数据会被丢掉。至于他俩到底怎么通信,那就是Qt内部的事情了。

  信号什么时候被激发?情况很多。比如button有click信号,在button被点击的时候就自动发出。更多时候我们需要手动发出自己的信号:

emit myOwnSignal(...);

用emit主动发出。

   至此你可以做信号和槽连接了。