通过上一篇博客《qt示例程序运行报错+解决办法+成功跑起来》,我们已经可以打开几乎(因为我没有试过每一个)任意(因为我试过的都成功跑起来了)一个示例程序了。
通过观察一些简单的示例和网上其他资料的学习,我发现一个qt项目一般包括3个部分:
- .pro 文件
- 头文件
- 源文件
一般如上图的样子。
上面的项目运行起来是这样子的:
感觉功能实现上还是挺不错的。
下面开始看其源代码。依旧是先上图,再分析
在执行上面红框中的语句时,执行了类的构造函数,而我们要做的东西大多就是这个构造函数。构造函数中再加入一些按钮和槽函数,就可以实现我们的功能了。
构造函数是类的构造函数,也就是在.h文件中声明、在.cpp文件中实现的函数。
class Calculator : public QWidget{Q_OBJECTpublic:Calculator(QWidget *parent = 0); // 构造函数private slots: // 一些计算的槽函数void digitClicked();void unaryOperatorClicked();void additiveOperatorClicked();void multiplicativeOperatorClicked();void equalClicked();void pointClicked();void changeSignClicked();void backspaceClicked();void clear();void clearAll();void clearMemory();void readMemory();void setMemory();void addToMemory();//! [0]//! [1]private:// 一些按钮//! [1] //! [2]Button *createButton(const QString &text, const char *member);void abortOperation();bool calculate(double rightOperand, const QString &pendingOperator);//! [2]//! [3]double sumInMemory; // 一些临时变量//! [3] //! [4]double sumSoFar;//! [4] //! [5]double factorSoFar;//! [5] //! [6]QString pendingAdditiveOperator;//! [6] //! [7]QString pendingMultiplicativeOperator;//! [7] //! [8]bool waitingForOperand;//! [8]//! [9]QLineEdit *display; // 编辑框//! [9] //! [10]enum { NumDigitButtons = 10 };Button *digitButtons[NumDigitButtons]; // 数字按钮数组};
先看.h文件中声明了什么: 这个类中有一个构造函数,一些槽函数、 一些按钮(包括数字),一些临时变量,就这些。(但是具体的起始我也没看懂,对应不上。不过先这么看吧。)
然后看这个类的实现:.cpp文件。
上面的代码是在构造函数中的,创建了许多按钮,也就是说整个计算器中有许多按钮不是一开始就有的,而是在构造函数中通过一个函数来创建的,并且在创建的时候给与不同的参数,换句话说,这些按钮的不同之处只有两点,也就是两个参数,其中后面一个是槽函数,也就是点击这个按钮时调用的函数。
接下来就是一个一个实现这些槽函数了。
在整个过程中,除了用到qt框架自带的类库之外,可能还需要自定义的类库,这时候就可能就要自己定义.h和.cpp
文件,例如本例中就自定义了Button类。
好了,程序外部大致框架是这样。
下面再讲讲内部实现的大致框架。我们以一个更简单的例子为例。
项目结构如下:
这是一个我根据网上教程自己敲的项目,就是一个简单的带有菜单栏的界面,使用到了槽函数的功能。下面介绍形成该界面的具体思路,也就是其构造函数的一般思路。
首先一个空的框MainWindow已经有了,因为他继承自MainWindow,想要增加一个菜单栏,栏就是Bar,菜单栏就是MenuBar,Qt的菜单栏就是QMenuBar,于是利用MainWindow的menuBar()函数构造一个这样的对象,并用一个QMenuBar*型的指针指向它。
这就有了菜单栏对象,里面有哪些菜单呢?现在我想添加一个文件菜单。
于是通过刚才的指针来调用对象的添加文件方法,并给其名称参数为“文件”,这就又定义了一个对象,是菜单栏对象里的一个子对象,我们再用一个指针来指向这个子对象。
菜单只是为了分类,我们最终想要的是一个动作,或者一个命令,例如新建。所以我们就利用刚才的指向文件菜单对象的指针,来调用文件菜单对象的addAction方法,来创建一个动作,并通过传参来给这个动作命名为“新建”,最后通过一个QAction * 类型的指针来指向这个动作对象。
现在,我们有了菜单栏、菜单、动作、以上三者,都是对象,并且是包含关系,主窗口对象包含菜单栏对象,所以可以调用主窗口对象的函数来创建菜单栏对象,同理通过菜单栏对象的方法来创建菜单对象,再通过调用菜单对象的方法来创建动作对象。
这个动作对象,怎么动作呢?可以通过接下来的connect函数。即lamda表达式形式的槽函数。
同理:
我们通过主窗口对象的addToolBar方法来创建工具栏对象,再通过工具栏对象的addAction方法来创建工具,这里有两种,一种是直接将之前创建过的动作对象指针作为参数传给方法,这样就像是一个快捷方式。
另一种是创建一个按钮,再调用工具栏对象的addWidget方法,相当于添加了一个按钮工具,这个按钮工具具体动作是什么呢?可以利用lamda表达式来实现,这里其实就和工具栏没什么关系了,只不过是将这个按钮放在了工具栏中。
从以上可以看出qt是面向对象的。所有的东西都是对象,包括菜单栏、菜单、动作、按钮,所有的方法,包括槽函数,都是属于某一个对象的,都是被事先声明好的。