Bootstrap

QT5学习笔记/顺带学C++

本文的标题顺序排布不局有普遍性,纯粹是我个人学习过程中学到哪记到哪,可能会非常跳脱


1.概念解释

  • Qt使用C++语法开发,语法上有着C++的特性,或者说Qt是C++的一个大型拓展库;但不意味着QT是一种语言,还存在PyQt:使用python开发的Qt
  • Qt面向对象的特性是由于C++的面向对象特性

面向对象编程:一种编程范式,与之对应“面向过程编程”

面向对象编程将程序抽象为几个部分包括“对象”“类”“封装”等等;


面向对象与面向过程的区别如下:

对于炒蛋炒饭,面向过程这样写:

1,先炒蛋

2,再炒饭

3,倒在一起炒

4,出锅

而面向对象这样写:

1,抽象出蛋、米饭、人、锅这几个对象

2,安排蛋这个对象其行为需要被炒

3,安排米饭这个对象其行为需要被炒

4,安排人这个对象其行为需要主动去炒

5,安排锅这个对象其行为需要加热

6,安排被炒后的蛋和米饭需要混在一起再被炒

7,以上6步一起执行然后得出蛋炒饭这个结果

现实中炒饭需要考虑先后顺序,这里仅举例说明两种范式的区别

  • QtCreator是方便开发者开发Qt的图形化开发环境,本质是一个工业软件,除了QtCreator,使用命令行控制台也可以直接开发Qt,只是不方便

2.Qt的编译/例程

控制台编译Qt的过程:

  1. 编写源代码

  2. 设置环境变量:
    注意需要将使用的编译器(mingw32)放置在环境变量列表的最上方,
    否则写完qt后运行会提示无法定位程序输入点于动态链接库

  3. 生成工程文件:
    控制台输入 qmake -project ,
    修改工程文件的最后一行添加 QT += Widget  gui,否则编译时会报错

  4. 生成makefile:
    控制台输入 qmake

  5. 编译:
    控制台输入 mingw32-make

最基本编译主函数结构:

#include<QApplication>//用到的Qt定义内容均需要添加include

int main(int argc,char *argv[])//argv属于指针数组变量,不要忘记[]
{
	QApplication app(argc,argv);//固定格式
	
	return app.exec();//主窗口需要永远存在,所以exec=程序永远执行(死循环
}

Qt最大的作用在于创建图形化的界面,对于一个图形界面,其文本描述、用户输入框、列表、展示的图片、交互按钮等,都被称之为控件

控件有标签、行编辑框、文本编辑框等,都属于对象,以windows的运行界面为例程,将其复现

图中红框部分均为不同控件对象,控件与控件之间的排布称为布局

使用Qt复现windows的运行窗口

#include <QApplication>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
//主程序中使用到了Qt定义的控件类型,故在头文件中需要事先加入对应的include
#include<QHBoxLayout>//Qt定义的水平布局,Qt中布局也是一种对象
#include<QVBoxLayout>//垂直布局
#include<QWidget>//窗口对象,整体窗口和程序对象Qapplication不是一回事
int main(int argc,char *argv[])
{
	QApplication app(argc,argv);//固定格式
	
	QLabel *infoLabel = new QLabel;//生成一个新的对象并被包含在某类中
	QLabel *openLabel = new QLabel;
    //new申请对象后返回的是地址,需要用指针去接收地址,所以定义新对象时均使用了指针
	QLineEdit *cmdLine = new QLineEdit;//行编辑控件,用于用户输入行文本
	QPushButton *commmitButton = new QPushButton;
	QPushButton *cancelButton = new QPushButton;
	QPushButton *browseButton = new QPushButton;
	
	infoLabel->setText("input cmd:");//对上一步创建好的对象编写该对象的行为例如设置文本
	openLabel->setText("OPEN");
	commmitButton->setText("commit");
	cancelButton->setText("cansel");
	browseButton->setText("browse");
	//以上调用的函数(如setText)均为无参构造,故没有()
	
	QHBoxLayout *cmdLayout = new QHBoxLayout;//创建布局对象以修改不同控件间的位置
	cmdLayout->addWidget(openLabel);
	cmdLayout->addWidget(cmdLine);//在刚刚创建的布局对象中添加需要调整位置的两个控件对象
	
	QHBoxLayout *ButtonLayout = new QHBoxLayout;
	ButtonLayout->addWidget(commmitButton);
	ButtonLayout->addWidget(cancelButton);
	ButtonLayout->addWidget(browseButton);//按钮部分也需要水平布局
	
	QVBoxLayout *mainLayout = new QVBoxLayout;//创建垂直布局对象
	mainLayout->addWidget(infoLabel);
	mainLayout->addLayout(cmdLayout);//在布局中添加布局,用的函数略有不同
	mainLayout->addLayout(ButtonLayout);
	
	QWidget w;//创建窗口,因为不涉及参数更改,故不用使用指针
	w.setLayout(mainLayout);//设置主窗口的行为,类似上面的->
	w.show();//设置完主窗口的总体布局还需要让窗口展示出来
	w.setWindowTitle("运行");//主题窗口的标题
	
	return app.exec();//主窗口需要永远存在,所以exec=程序永远执行(死循环
}

编写完后,进行控制台编译,以minGw 7.3为例运行

控制台编译Qt仅用作了解编译过程学习,正常开发中不会使用这种方法,效率极低。

3.QtCreator/信号与槽

3.1QtCreator

创建工程的类选择中 Qmainwindow 与Qwidget有所区分,

一般的小窗口属于Qwidget类,如微信登陆窗口;

带有菜单的完整界面窗口为Qmainwindow类,如各微信主界面;Qdialog类是一般的对话框。


QtCreator将Qt程序开发分为两类,一类逻辑代码,一类界面设计

在逻辑代码在“编辑”中开发,编写软件项目后台的逻辑操作;

界面设计在“设计”中开发,是纯图形化的设计界面,保存为.ui后缀文件,在这个栏目的操作仅为设计定制将要开发的软件交互界面,如按钮摆放位置,窗口大小形状等,按钮按下的后续逻辑响应需要用到信号与槽机制。

3.2信号与槽 

对按钮或其他动作触发的响应称为信号,信号需要传递给槽函数执行,槽函数就是其响应结果

可以在设计图形化界面中右键直接创建槽接口,QtCreator会自动补全需要的语法语句,手动编写时,槽函数在主程序文件中编写完后,还需要在头文件中进行声明 ,例如“取消按钮”按下后会触发一个信号,处理该信号的槽函数为:

void Widget::on_cancelButton_clicked()
{
    this->close();
}

其作用是关闭这个父类 ;除此之外还需要在头文件中声明

private slots:

    void on_cancelButton_clicked();

槽函数的作用就是触发响应信号后执行的结果,有了结果还需要和对应的信号连接起来,由此引出非常重要的函数connect

connect定义为:


connect(谁发出信号,发出的信号,谁接收信号,接收后怎么处理);

 在上述例子中对应的connect函数语句为


connect(ui->cancelButton,&QPushButton::clicked,this,&Widget::on_cancelButton_clicked);

此为connect的一种写法,取类地址后添加动作函数 ,还有一种connect写法:


connect(ui->cmdLine,SIGNAL(returnPressed()),this,SLOT(on_commitButton_clicked()));
/*ui指针指向的成员cmdline发出信号,
  cmdline属于QlineEdit该类中对回车键的信号描述为上文所示,
  交给父类进行处理,然后将信号连接到对应槽函数*/

 其作用为将输入行触发的回车键按下的信号连接到commitButton这个按钮上

而commitButton按钮对应的槽函数为

void Widget::on_commitButton_clicked()
{
    QString program = ui->cmdLine->text();
    QProcess *myProcess = new QProcess(this);//创建process对象
    myProcess->start(program);
}

Line3是说,QString这个类中的Program这个自定函数对象的值来自于ui指针指向的成员cmdLine的text函数的值,text函数的作用是接收用户输入的数据(字符串)按键按下后会接入到QProcees函数里,QProcess会调用windows同名进程,故commitButton按键的作用就是接收用户输入的字符串,然后打开windows中相应的进程,若用户输入的字符不是windows的进程之一则无响应。

另外设置按钮对应触发进程前,头文件需要添加 #include <QProcess>

4.部分C++语法

4.1类与结构体

如果要定义的一种包含多子类的数据,他各个子数据包含各自的行为属性(成员函数),就要使用class定义

class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明
      double volume(void);
      void set( double len, double bre, double hei );
};
// 成员函数定义
double Box::volume(void)
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}

如果要定义的一种包含多子类的数据,他各个子类仅有数据,没有行为属性,就没必要使用class,struct结构体即可

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

在C++中,类class 和 结构体struct 均可以定义成员函数(但是C语言中struct不能指定成员函数,仅有成员数据) 其区别仅在定义的初始访问变量的优先级不同(作用域不同)

class A
{
    int a; //此处的a变量是私有的,仅在A作用域内
}

struct B
{
    int a; //此处的a变量是公有的,不需要通过public来声明
}

;