Qt知识点汇总

说明

最近加入T公司,需要使用Qt进行PC下的界面应用开发,因此总结了一些Qt的常见用法在这里,以便学习(我一个linux后台开始玩Qt,也是造化弄人);

QT UI

QT开发过程中,QT通过一个后缀为ui的文件来描述应用程序的界面信息,该ui文件内容实质上是要给xml文件。

在开发过程中,可以通过相关的UI工具(例如qtDesinger)等工具生成该ui文件。

在编译过程中,该ui文件会被qt的ui处理工具uic转换为标准的c++文件, 生成的标准c++文件可以被引用以及被标准c++编译器编译。

非集成开发环境下,uic工具使用如下:

在集成开发环境中,大部分情况下ui文件会被转换为ui_XXX.h文件。

Qt 资源文件

在QT应用开发中,通过qrc文件描述应用使用到的资源文件(图片,音视频等)。Qrc文件的实质是一个xml文件,在文件中描述了资源名称与资源文件的关系,qt提供了一个工具rcc将qrc文件转换成标准的cpp文件,然后可以通过标准c++编译器使用该资源文件信息。

对于外挂资源,可以通过在rcc工具执行时添加-binary参数达到,添加后生成一个rcc文件,在代码中通过QResource::registerResource("/path/to/myresource.rcc");可以将该外挂资源集成到应用程序内部进行使用。

QT UI文件编译

Vs2019开发环境与QT集成后,ui界面文件x.ui对应的ui_XX.h文件由uic.exe自动生成,该生成文件路径可以通过以下方式设置:

右键ui文件选择属性,调整output变量取值。

QT+VS2019命令行编译

项目目录下执行以下命令

qmake -project QT+=widgets

qmake

nmake Debug Release

注意事项

打开的vs2019 cmd命令行,需要根据实际情况选择对应的架构x86或x64

QT MOC机制

QT的元对象系统是一个基于标准C++的扩展,能够使c++更好的适应GUI编程,支持开发人员在执行期获取对象的信息,同时这一机制也支持属性以及文本翻译(国际化,多语言)。

由于标准C++并没有提供动态元信息的支持,因此qt通过一个单独的工具moc来处理这个问题,moc工具会解析头文件中被Q_OBJECT宏声明的类,并生成一个单独的标准cpp文件来实现,因此对任何c++编译器而言,QT的moc机制都可以正常工作。

在具体的代码编写中,只有继承自QObject的类中,才可以通过宏Q_OBJECT进行修饰,从而转变成要给元对象。

对于一个元对象,它有如下一些特点

1:可以支持QT特有的signals和slots机制,在不同对象之间进行通信。

2:可以支持QObject::metaObject方法,用于返回类关联的元对象。

3:可以支持QMetaObject::className,用于在执行期获取对象的类名。

4:可以支持QObject::inherits方法,用于判断一个对象是否继承自QObject

5:可以支持QObject::setProperty和QObject::property方法,用于动态的设置和获取属性名称。

6:可以支持通过QMetaObject::newInstance用于构造一个新的实例。

在使用QT的MOC机制时,存在的一些限制

1:不能对模板类使用MOC机制(模板类无法继承自QObject)。

2:多重继承时QObject必须是第一个,且不支持QObject的虚继承。

3:函数指针不能作为信号或槽的参数。但通过typedef简化后的函数指针可以作为槽函数的参数。

4:信号和槽函数的参数必须是完全名称限定。

5:内嵌类不能有信号和槽。

6:信号和槽函数返回不能是引用。

QT中的信号和槽

信号(signal),就是特定情况下被发射的事件。

槽(slot)就是对信号的响应函数,就是一个函数。

Signal与slot之间的关联,是通过QObject::connect函数实现, 基本格式如下:

QObject::connect(sender,SIGNAL(signal()), receiver, SLOT(slot()))。

一个singal可以connect到多个slots;多个signal可以connect到同一个slot;一个signal可以connect到另外一个signal。

在使用signal与slots的类中,该类必须被宏Q_OBJECT修饰。

一般情况下,当一个signal被发射,与其关联的slot函数会立即被执行,只有所有slot函数被执行完成后,signal后的代码才会被执行。

自定义slot函数:

                任意的类成员函数,普通全局函数,静态函数都可以当做slot函数处理。Slot函数必须与signal信号一致(参数和返回值)。

自定义信号:

                信号必须通过关键字signal进行声明,signal没有返回值,但可以有参数,signal就是函数声明,无需实现。通过emit关键字进行signal的发射。

QT中几种connect到slot的方式

// 传统Qt4连接方式为 信号发送者,信号,信号接受者,处理函数

   QObject::connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(qT4_slot()));

//Qt5的新方法,在编译的时候就会有监测,如果我们手误操作失误,就会出现问题

    QObject::connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::qT5_slot);

  //Qt5 Lambda表达式

    //这里需要注意 Lambda表达式是C++ 11 的内容,所以,需要再Pro项目文件中加入CONFIG += C++ 11

   QObject::connect(ui->pushButton_3,&QPushButton::clicked,[=](){qDebug()<<"lambda表达式";});

QT事件机制

事件的产生:

                当用户按下鼠标/键盘等外部输入时产生事件,系统定时器,其他组件主动发起等也产生事件。

                Qt中所有的事件都继承自QEvent基类。

任何事件发生后,都会生成一个Event对象,该对象会被传递给特定组件的event处理函数,该event对象包含事件发生时所需要交互的所有信息。

            在应用执行过程中,用户可以产生自定义事件,有两种方式产生事件,一种是调用postEvent接口,另外是通过sendEvent接口产生,postEvent产生的是异步事件,事件会被放入Qt消息队列中,等待被依次处理,sendEvent产生的事件不会放入队列,而是直接派发和处理。

事件的处理:

            每个组件都定义了一组mousePressEvent相关的函数,用于处理对应的事件。对于自定义组件,可以通过重写这些方法对事件进行特殊处理。

                此外通过重新组件的event接口可以控制是否对某个事件进行处理。

事件过滤:

                有多个组件对象,例如A,B,通过A监视B的事件,可以在A中处理传递给B的事件。其基本过程如下:

                首先B调用installEventFilter接口注册监视对象A(如果有多个组件都需要被A监视,其他组件也需要调用该接口注册A)。

                在A的eventFilter接口中对事件进行处理,即如果一个事件被发送给B,在该事件被B处理之前,会优先调用A的eventFilter接口,在该接口中可以具体完成特定功能。

QT关键组件及使用方法

GraphicView

Graphic View是QT4之后面向对象的绘图机制,主要包括三个主要的类,QGraphicsScene(场景),QGraphicsView(视图),QGraphicsItem(图元),其中QGraphicsScene本身不可见,是一个存储QGraphicsItem的容器,要呈现QGraphicsScene内的内容,必须将QGraphicsScene与QGraphicsView关联起来进行交互;QGraphicsScene主要提供了操作QGraphicsItem的接口,事件传递以及无变换绘制等功能。

QGraphicsView提供了一个窗口,用于显示QGraphicsScene中的QGraphicsItem,一个QGraphicsScene场景可以关联多个QGraphicsView进行显示。

QGraphicsItem是需要呈现的基础类,QT提供了一些已经封装好的标准类,主要有下面这些:

QGraphicsSimpleTextItem:提供了一个简单的文本标签项

QGraphicsTextItem:提供了一个格式化的文本项

QGraphicsLineItem:提供了一个直线项

QGraphicsPixmapItem:提供了一个图像项

QGraphicsRectItem:提供了一个矩形项

QGraphicsEllipseItem:提供了一个椭圆项

QGraphicsPathItem:提供了一个路径项

QGraphicsPolygonItem:提供了一个多边形项

QgraphicsView坐标系

Graphics View坐标系基于笛卡尔坐标系,图元的位置和几何形状通过x坐标和y坐标表示,当使用没有变换的试图观察场景时,场景中的一个单位对应屏幕上的一个像素。在GraphicsView架构中,主要有3个有效坐标系统。

图元坐标:图元坐标位于自己的本地坐标上,图元的坐标通常以图元中心为原点,x轴向右,y轴向下,在自定义图元时,只需要注意图元的坐标既可。

子图元的坐标与父图元的坐标相关,如果子图元无变换,子图元坐标与父图元坐标相同,父图元变换时,子图元会隐式的被变换,但子图元的坐标不会被父图元的变换所影响。

场景坐标:场景坐标是所有图元的基础坐标,场景坐标描述了最顶层的图元位置,每个图元在场景中都有场景坐标和边界矩形,场景坐标的原点在场景中心,x轴向右,y轴向下。

视图坐标:视图坐标是窗口部件的坐标,视图坐标的单位是像素,左上角是远点,为了与图元交互,需要将图元坐标转换为场景坐标。

在Graphics View中,提供了对应的接口在几个坐标系之间进行转换。

QGraphicsView::mapToScene()视图到场景

QGraphicsView::mapFromScene()场景到视图

QGraphicsItem::mapFromScene()  场景到图元

QGraphicsItem::mapToScene()  图元到场景

QGraphicsItem::mapToParent()  子图元到父图元

QGraphicsItem::mapFromParent()父图元到子图元

QGraphicsItem::mapToItem()本图元到其他图元

QGraphicsItem::mapFromItem()其他图元到本图元

例如如果想在view坐标的原点开始绘制一条线段,可以通过如下方式处理

   1:调用view接口QGraphicsView::mapToScene()将view原点变换到scence坐标系中。

   2:调用item接口QGraphicsItem::mapFromScene()  将坐标从scence变换为item坐标系,然后调用item的setLine接口进行线段绘制。

样例代码如下:

QgraphicsView上绘制可编辑文字

QgraphicsView展示图片

QGraphicsView上展示图片可以通过QPixmap类以及接口addPixmap实现。样例代码如下:

常见问题

1:error C2001: 常量中有换行符

QT编码中,字符串中存在中文等字符时,有时候会报“error C2001: 常量中有换行符”错误,对于该错误,可以在字符串后面添加一个空格规避。

2:QgraphicsView坐标对齐

默认情况下scence的原点会出现在view的中间,此时可以通过调用setAlignment进行对齐。

例如以左上角方式对齐:

view->setAlignment(Qt::AlignLeft | Qt::AlignTop); 在这种方式下绘图比较方便。

3:QgraphicsView曲线平滑

此外进行线条绘制时,默认并没有开启线条平滑,此时可以通过调用view->setRenderHint(QPainter::Antialiasing);设置平滑线条。

你可能感兴趣的:(Qt知识点汇总)