当前位置: 首页 > news >正文

建站平台需要授权吗东莞谷歌推广公司

建站平台需要授权吗,东莞谷歌推广公司,怎么建立公司官网,建盏厂家联系电话目录 1.Qt简介和案例 2.第一个Qt程序 3.学会查看帮助文档 4.创建一个按钮 5.对象树简介 6.Qt的坐标系 7. 信号和槽 7.1自定义信号和槽 7.2信号连接信号 7.3拓展 7.4Qt4版本以前的connect 1.Qt简介和案例 Qt是一个跨平台的C图形用户界面应用程序框架(就是一个库吧…

目录

1.Qt简介和案例

2.第一个Qt程序

3.学会查看帮助文档

4.创建一个按钮

5.对象树简介 

6.Qt的坐标系

7. 信号和槽

7.1自定义信号和槽

7.2信号连接信号

7.3拓展

7.4Qt4版本以前的connect

1.Qt简介和案例

Qt是一个跨平台的C++图形用户界面应用程序框架(就是一个库吧),它是完全面向对象的,允许真正意义上的组件式编程。

Qt是Linux桌面环境KDE的基础,它有商业版和开源版。

Qt的成功案例有很多,例如Linux桌面环境KDE、WPS等等。

它的优点如下:

  • 跨平台,几乎支持所有平台
  • 接口简单
  • 一定程度上简化了内存回收机制(对象树)
  • 可以进行嵌入式开发

2.第一个Qt程序

在创建项目时会提示选择三个基类当中的某一个:

这三个基类之间的关系如下:

QMainWindow和QDialog继承自QWidget:

  • QWidget是一个空白窗口
  • QMainWindow是一个带有菜单栏、工具栏、状态栏等等的一个窗口
  • QDialog是一个提示对话框 

项目创建完成后会有一个".pro"文件,这个文件时当前项目的工程文件,里面有一些很重要的内容,不要不要随意修改".pro"文件的内容甚至不要加注释。

可以看到默认情况下,Qt包含了core模块和gui模块,如果是4版本以上的话还会添加一个widgets模块。原因在于4版本以前widgets模块属于gui模块,4版本以后将widgets独立出来了。 

当前项目自动构建出了一些源文件和头文件,可以很轻松的找到主函数:

其中,应用程序对象有且仅有一个, Widget类继承自QWidget,调用该类的show方法可以单独显示一个窗口:

注意Widget类定义当中的"Q_OBJECT",这是一个宏,它的作用是让该类支持信号和槽机制。还要注意其构造函数,有一个名为parent指向QWidget类的指针,这与对象树有关,稍后做解释。

3.学会查看帮助文档

学习任何技术都需要有帮助文档,Qt提供了这样的帮助文档。选中关键字并且按下"F1"可以弹出帮助文档

还有一种方法是直接打开帮助文档的独立引用程序,它的位置在"Qt安装路径/版本号/mingw_64/bin"下:

 

4.创建一个按钮

Qt当中的按钮类为"QPushButton",通过帮助文档可以查看的到:

 接下来在代码当中创建一个按钮并让其显示:

#include "widget.h"#include <QApplication>
#include <QPushButton>  // 包含头文件
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;QPushButton *btn = new QPushButton;btn->show();// 显示w.show();return a.exec();
}

可以看到如果使用QPushButton类的show方法,是单独打开一个窗口并显示。很显然这并不是想要的效果。如果想要依附于已存在的窗口显示,只需要为按钮指定一个父亲即可

#include "widget.h"#include <QApplication>
#include <QPushButton>  // 包含头文件
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;QPushButton *btn = new QPushButton;btn->setParent(&w);// 依附于已经存在的窗口//btn->show();// 显示w.show();return a.exec();
}

此时按钮便依附于已存在的窗口了。如果想要设置一下按钮的大小、显示文字、改变位置,可以使用QPushButton类的某些成员函数:

#include "widget.h"#include <QApplication>
#include <QPushButton>  // 包含头文件
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;QPushButton *btn = new QPushButton;btn->setParent(&w);// 依附于已经存在的窗口btn->setText("First Button");// 显示文字btn->resize(200,200);// 设置一下按钮的大小btn->move(200,100);// 移动到指定为止//btn->show();// 显示w.resize(600,400);// 固定一下窗口的大小w.show();return a.exec();
}

5.对象树简介 

在没有接触Qt之前,上面的代码对于C++程序员来说是难受的,因为new了一个QPushButton对象却并没有做delete操作。

事实上在Qt当中有些情况下并不需要做delete操作,这就是对象树的作用。

对象树是Qt当中的一种自动回收内存的机制,它可以简化程序员的工作。就如上面的代码,程序员可以不用担心内存泄漏,即不用delete。

想要不delete堆上的内存空间,必须符合两个条件:

  • new出来的对象必须是QObject的亲缘类对象
  • 该对象必须指定一个QObject的亲缘类对象

QObject是最顶层的基类,基本上Qt当中的内置类都继承自于QObect。因此比如QWidget、QMainWindow、QDialog、QPushButton等等,它们的最顶层的基类就是QObject。

当new出来的对象指定了父亲之后,就相当于加入了对象树。这颗对象树的任意节点(对象)析构时,会自动释放其所有子孙节点(对象)。

此时可以做一个实验,即自定义一个类,取名为"MyTest"并继承自QPushButton类,指定它的父亲为Widget类:

#ifndef MYTEST_H
#define MYTEST_H#include <QWidget>
class MyTest : public QWidget
{Q_OBJECT
public:explicit MyTest(QWidget *parent = nullptr);~MyTest();
signals:};#endif // MYTEST_H
#include "mytest.h"
#include <QDebug>
MyTest::MyTest(QWidget *parent): QWidget{parent}
{}MyTest::~MyTest()
{qDebug() << "~MyPushButton()";
}

修改一下Wdiget类的析构函数:

#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent): QWidget(parent)
{
}Widget::~Widget()
{qDebug() << "~Widget()";
}

然后在主函数当中new出来MyPushButton类,指定其父亲为Wdiget,运行后关闭窗口观察打印结果:

#include "widget.h"#include <QApplication>
#include <QPushButton>  // 包含头文件
#include "mytest.h"
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;MyTest *mbtn = new MyTest(&w);w.resize(600,400);w.show();return a.exec();
}

关闭窗口后的输出结果,可以看到mbtn所指向的堆空间并没有手动delete,但是由于对象树的存在,不会造成内存泄漏。 

这里可以用一幅图来解释:

此时可能会有个问题,即刚才说的是对象树当中的某个对象释放时会先析构其所有子孙节点。那么为什么先打印父对象的析构,后打印子孙对象的析构呢?这个原因在于析构函数分成两部分执行,一是执行析构函数函数体内的代码,二是执行函数体之后的清理工作。函数体内的代码是释放当前对象的大部分资源,例如对象内部new出来的空间;函数体之后是清理对象本身。所以对象树可以理解成清理对象本身之前先析构其所有子孙对象。 

6.Qt的坐标系

Qt的窗口是有坐标系的,上面在控制按钮的位置时涉及到坐标系。Qt窗口的坐标系如下图所示:

7. 信号和槽

其实信号和槽可以理解为"信号和信号处理"。熟悉Linux系统编程的话,理解信号和槽不会太难。

信号和槽涉及到两个角色,即信号的发送方和信号的接收方;涉及到两个动作,即信号的发送和信号的处理。

总体而言可以分成两个部分:

connect是一个函数,作用类似于Linux当中的signal()。它的作用我个人理解成"注册一个信号产生时需要做的动作"。 

通过帮助文档可以查看该函数:

原型可以是这样的:

connect(信号的发送发,要发送的信号,信号的接收方,接收到信号后要做的动作) 

做一个小任务,即创建一个按钮,点击该按钮后关闭窗口:

#include "widget.h"#include <QApplication>
#include <QPushButton>  // 包含头文件#include "mytest.h"
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;QPushButton *btn = new QPushButton(&w);btn->setText("PushButton");btn->move(200,100);btn->resize(100,100);QObject::connect(btn,&QPushButton::clicked,&w,&Widget::close);// 注册信号w.show();return a.exec();
}

该按钮点击后,窗口就关闭了。 

综上,信号和槽的优点非常明显:

  • 使得编程多样化,可以实现更多丰富的功能,非常自由
  • 低耦合,信号的发送方和接收方是低耦合的,这样设计有利于代码维护,出错的概率降低

7.1自定义信号和槽

如果自定义了一些类,并且想让这些类也能够使用信号和槽机制,Qt是支持的。

创建一个Student类和Teacher类,signals关键字下写自定义信号函数,该函数只声明不实现;public slots关键字(较高版本的Qt可以写到public下和全局下)下写自定义槽函数,该函数要声明和定义。

当前的任务是Teacher发出一个"下课"信号,学生做出"走出教室"动作。

#ifndef TEACHER_H
#define TEACHER_H#include <QObject>class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:void ClassOver();// 下课,只声明不实现
};#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H#include <QObject>class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);void GoOutOfClass();// 要声明和实现
signals:};#endif // STUDENT_H
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent): QObject{parent}
{}
void Student::GoOutOfClass()
{qDebug() << "学生走出教室!";
}

此时在主函数当中完成任务:

int main(int argc, char *argv[])
{QApplication a(argc, argv);Student *stu = new Student;Teacher *tec = new Teacher;QObject::connect(tec,&Teacher::ClassOver,stu,&Student::GoOutOfClass);emit tec->ClassOver();// emit关键字,发送信号delete stu;delete tec;return a.exec();
}

此时要注意一个关键字,即"emit",它的作用在于触发信号。 

其他方面,无论是信号函数还是槽函数,都是可以带参数的

这里再做一个实验,即让信号函数之间发生重载,槽函数之间发生重载:

#ifndef TEACHER_H
#define TEACHER_H#include <QObject>
#include <QString>
class Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr);signals:void ClassOver();// 下课,只声明不实现void ClassOver(QString str);
};#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H#include <QObject>
#include <QString>
class Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent = nullptr);void GoOutOfClass();// 要声明和实现void GoOutOfClass(QString str);
signals:};#endif // STUDENT_H
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent): QObject{parent}
{}
void Student::GoOutOfClass()
{qDebug() << "学生走出教室!";
}void Student::GoOutOfClass(QString str)
{qDebug() << "老师说:" << str;
}

那么在主函数当中修改一下代码:

int main(int argc, char *argv[])
{QApplication a(argc, argv);Student *stu = new Student;Teacher *tec = new Teacher;QObject::connect(tec,&Teacher::ClassOver,stu,&Student::GoOutOfClass);emit tec->ClassOver("下课啦!");// emit关键字,发送信号delete stu;delete tec;return a.exec();
}

此时出现了编译报错!原因在于connect函数当中的参数,信号函数和槽函数根本没有明确唯一指向,导致编译器报错。解决方法是利用函数指针来明确唯一指向

int main(int argc, char *argv[])
{QApplication a(argc, argv);Student *stu = new Student;Teacher *tec = new Teacher;void (Teacher::*tecSignal)(QString) = &Teacher::ClassOver;void (Student::*stuSlot)(QString) = &Student::GoOutOfClass;QObject::connect(tec,tecSignal,stu,stuSlot);emit tec->ClassOver("下课啦!");// emit关键字,发送信号delete stu;delete tec;return a.exec();
}

需要注意,在声明和定义槽函数时,它们的返回值都为void

如果需要取消注册的话,可以使用disconnect函数,这里就不做示例了。

7.2信号连接信号

信号不一定非要与槽函数connect在一起,信号和信号之间也可以连接。

现在实现一个需求,即创建一个按钮,按钮点击后老师下课,学生走出教室。此时代码可以修改为:

int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;Student *stu = new Student(&w);Teacher *tec = new Teacher(&w);void (Teacher::*tecSignal)() = &Teacher::ClassOver;void (Student::*stuSlot)() = &Student::GoOutOfClass;QObject::connect(tec,tecSignal,stu,stuSlot);QPushButton *btn = new QPushButton(&w);btn->setText("PushButton");btn->resize(200,100);QObject::connect(btn,&QPushButton::clicked,tec,tecSignal);w.resize(600,400);w.show();return a.exec();
}

此时点击按钮会让老师产生下课信号,随后学生走出教室。

但是注意这里有个非常局限的东西,那就是信号连接信号时,作为槽函数的信号函数无法传递参数!这个时候就要配合全局函数或者lambda表达式,即在它们内部触发信号!

7.3拓展

下面的规则是总结和拓展:

  • 一个信号可以连接多个槽函数
  • 多个信号可以连接同一个槽函数
  • 信号和槽函数的参数类型必须一一对应
  • 信号函数的参数个数可以多于槽函数的参数个数

对于规则3和4的解释为,槽函数和可以选择接收和不接受信号传递过来的参数,如果选择接收了信号的参数,那么类型必须一致。以一幅图来理解:

7.4Qt4版本以前的connect

上面介绍的都是Qt4版本之后的connect函数用法,在Qt4版本之前,写法是下面这样的:

QObject::connect(tec,SIGNAL(&Teacher::ClassOver(QString)),stu,SLOT(&Student::GoOutOfClass(QString)));

显然这样的方式是非常直观的,因为可以免除函数指针的繁琐写法。但是这种写法必然存在恶劣的缺点否则较新的Qt版本也不会出现较新的写法。

根本原因在于SIGNAL和SLOT关键字会将括号内容字符串化,并且这些字符串之间还不会做任何的比较,所以导致编译器无法报错,导致后续维护项目困难。 

http://www.hkea.cn/news/851837/

相关文章:

  • 嘉兴类网站系统总部网站建设技术解决方案
  • 做网站的教科书外包网络推广公司推广网站
  • 模板名字 wordpress优化大师如何删掉多余的学生
  • 3d网站建设制作百度关键词优化手段
  • 新手做那些网站比较好东莞企业网站排名
  • 欧美风格网站360指数
  • 优秀网站建设公司电话下列哪些店铺适合交换友情链接
  • 58同城乌鲁木齐网站建设重庆网站到首页排名
  • wordpress知言主题山东服务好的seo公司
  • 旅游商务平台网站建设功能需求关键词排名查询官网
  • 做网站要搭建本地服务器么微商引流被加方法精准客源
  • 网站名字要备案吗友情链接怎么弄
  • 江苏网站开发外链网站大全
  • 网站代备案流程图百度关键词优化排名技巧
  • 石狮建设局网站今日头条站长平台
  • 修改公司网站网页站长素材音效
  • 网站速度测速免费访问国外网站的app
  • 常州网站搭建公司宣传推广渠道有哪些
  • 中国建设监理网站广告网络
  • 网站维护费用怎么收路由优化大师官网
  • 如何加入小说网站做打字员合肥网站优化推广方案
  • 网站建设现状关键词在线优化
  • 网站建设就业百度网址导航主页
  • 郑州公司做网站汉狮中囯联通腾迅
  • 专业网上购物平台优化网站的步骤
  • 用web开发一个网站怎么做网站推广优化平台
  • 建设企业网站进去无法显示搜索引擎seo
  • 网站 分辨率百度视频推广
  • 中国红河网seo排名工具
  • 做网站商丘3a汽车集团公司网络营销方案