阅读Qt demo笔记——关于图像视图框架和状态机框架

来源:互联网 发布:网络信息采集技术 编辑:程序博客网 时间:2024/06/05 17:46

此篇文章主要是讲解Qt Demo中的一个软件示例所用到的技术。

软件代码链接:http://pan.baidu.com/s/1gduYcy3

 

一:图像视图框架

1、QGraphicsScene类与QGraphicsView类
QGraphicsScene类是逻辑接口,不提供ui显示,只对2D图形项进行管理,相当于一个容器。
QGraphicsView类为显示QGraphicsScene类的内容提供窗体。
为了达到让2D图形项显示出来的目的,以上两个类一般会搭配使用,这两个类的构造函数如下:
QGraphicsScene::QGraphicsScene ( const QRectF & sceneRect, QObject * parent = 0 )
QGraphicsView::QGraphicsView ( QGraphicsScene * scene, QWidget * parent = 0 )
可以看出QGraphicsView类需要QGraphicsScene类定义的变量作为参数,例子如下:
 QGraphicsScene scene;
 scene.addText("Hello, world!");

 QGraphicsView view(&scene);
 view.show();
由于QGraphicsView类可提供ui界面,因此他具有ui界面的各种属性。
QGraphicsScene类可以添加多种图形项,可供调用的函数有:addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(), addText(), addItem(), addWidget().
通过这些函数添加进来的图形项会在Scene变量的逻辑中心点被部署,然后可以使用setPos()函数来调整位置,也就是说Scene变量的逻辑布局是有坐标系的,坐标系的中心点为(0,0),在定义一个Scene变量时会输入4个相对于(0,0)位置的偏移量,如下:
QGraphicsScene scene(-350, -350, 900, 900);
通过这4个偏移量可以确定逻辑布局图的宽高,而这个宽高进而会成为View变量的宽高,也就是我们肉眼看到的窗体的宽高(默认情况下是Scene变量的宽高,不过View变量也可以通过函数对宽高进行更改)

2、QGraphicsItem类
上面提到的向Scene变量添加图形项的函数中有一个是比较特殊的,那就是addItem(),它是向Scene变量中添加QGraphicsItem类图形项。
QGraphicsItem类是所有图形项的基类,它为编写开发人员自己的图形项提供基础。为了便利,Qt提供了一套标准的图形项,如下:
QGraphicsEllipseItem provides an ellipse item   (椭圆图形项)
QGraphicsLineItem provides a line item   (线图形项)
QGraphicsPathItem provides an arbitrary path item (任意路径图形项)
QGraphicsPixmapItem provides a pixmap item  (像素图形项)
QGraphicsPolygonItem provides a polygon item  (多边形图形项)
QGraphicsRectItem provides a rectangular item  (矩形图形项)
QGraphicsSimpleTextItem provides a simple text label item (简单文本图形项)
QGraphicsTextItem provides an advanced text browser item (富文本图形项)
这些类都是QGraphicsItem类的子类,因此都可以被addItem()函数添加到Scene变量中。
值得一提的是,每个QGraphicsItem类型的图形项(包括这一套标准的图形项)都会拥有一个z值,这个z值决定了这个图形项在相邻图像项中的栈序,换句话说,这个z值相当于每个图形项的ID(想象一下,如果Scene变量中有很多个相同的图形项,但却没有一个ID可以标记每个图形项,那会有多么的混乱),z值越高越会绘制在窗体的上层。
图形项还可以拥有自己的子图形项,而且子图形项可以在父图形项上进行布局,因为每个图形项都有一套类似Scene变量的坐标系。

总结一下这3个类:
QGraphicsItem类——创建图形项,有很多图形项子类
QGraphicsScene类——图形项容器,对图形项进行管理
QGraphicsView类——创建ui,将容器中的图形项显示到屏幕上

3、创建自己的图形项类
既然有了上面提及的一套标准的图形项类,为什么我们还要创建自己的图形项类呢,答案很简单,因为无法满足需要。有时我们会要求显示出来的图形项具有更多的功能,比如点击一下会弹出一个对话框或者其他,有人会说了,在View变量中添加pushButton不就得了,这当然可以,但这样pushButton就不是图形项了,它也就没有图形项的优点了。为了兼具图形项和其他功能,我们需要创建自己的图形项类。
通过子类化QGraphicsItem类或者子类化QGraphicsWidget类均能达到创建自己的图形项类的目标,这两个类有些相似,因为这两个类都拥有用于绘制图形项的函数(因为QGraphicsWidget类重载了QGraphicsItem类中的这些函数),但也有很大的不同,QGraphicsWidget类兼具窗体的特征,这是QGraphicsItem类所不具备。
因此,如果你想创建一个具有窗体性质的图形项,那就子类化QGraphicsWidget类吧;如果你想创建一个不具有窗体性质的图形项,那可以考虑子类化QGraphicsItem类。
其实实际上,我们直接子类化QGraphicsWidget类就可以,不用考虑是否会需要窗体性质。
接下来说说如果通过子类化QGraphicsWidget类来创建自己的图形项类。
关键就在于下面的3个虚函数:

QRectF QGraphicsWidget::boundingRect () const [virtual]
这个函数定义了图形项的外部矩形边界,所有的绘制必须被限制在这个边界内部进行,QGraphicsView依靠这个边界来决定图形项是否需要被重新绘制。

QPainterPath QGraphicsWidget::shape () const [virtual]
这个函数返回图形项的轮廓,默认实现调用boundingRect ()函数,返回简单的矩形轮廓。有很多地方会调用这个函数。

void QGraphicsWidget::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ) [virtual]
这个函数通常会被QGraphicsView调用,用于绘制图形项的内容。painter用于绘制,option提供风格选项。

 

二:状态机框架

状态机框架用于创建和执行状态转换图(state graphs)
1、QStateMachine类
此类提供一个分等级的有限的状态机。
这个状态机管理一系列状态以及状态之间的转换。这些状态和转换组成了一个状态转换图。一旦状态转换图被建立,这个状态机就会执行他。
可以通过addState()添加状态,也可以使用removeState()移除状态,但当状态机正在运行时移除状态会失败。
在开始状态机之前要设置初始状态。

2、QState类
此类为状态机提供一个通用的状态。
一个状态可以拥有多个子状态,并且可以转换到其他状态。
可以通过addTransition()添加转换,也可以通过removeTransition() 移除一个转换,transitions()函数返回当前状态的对外转换。
assignProperty()函数很重要,用于设置状态所绑定的对象的属性,当进入这个状态时,预定的这些属性便会被设置到所绑定的对象中,函数声明如下:
void QState::assignProperty ( QObject * object, const char * name, const QVariant & value )
解释:在进入状态时,将object对象中的name属性的值设置成value。
那么如何在QObject类型的对象中自定义一个属性呢?使用下面这个宏即可:
 Q_PROPERTY(type name
            READ getFunction
            [WRITE setFunction]
            [RESET resetFunction]
            [NOTIFY notifySignal]
            [DESIGNABLE bool]
            [SCRIPTABLE bool]
            [STORED bool]
            [USER bool]
            [CONSTANT]
            [FINAL])
例如:Q_PROPERTY(QPointF pos READ getPos WRITE setPos)
解释为:第一个属性,属性的类型为QPointF,属性的名字为pos,属性的读取函数为getPos,属性的写入函数为setPos。
这个属性类似于QObject中的一个成员(变量)。

3、Transition
现在具体的看一下如何如何连接2个状态。
上面提到了addTransition()可以添加转换,这个函数有3种定义,如下:
1——void QState::addTransition ( QAbstractTransition * transition )

2——QSignalTransition * QState::addTransition ( QObject * sender, const char * signal, QAbstractState * target )

3——QAbstractTransition * QState::addTransition ( QAbstractState * target )

第一种:直接添加给出的转换transition 到状态中,transition 可能是已经建立的一个转换;
第二种:在当前状态下,如果实例sender发送了signal信号,则将状态转换为target状态,此函数拥有一个QSignalTransition *类型的返回值,因此外接可以对这个转换进行额外的操作(比如添加动画);
第三种:直接添加要转换到状态target,此函数拥有一个QAbstractTransition *类型的返回值,因此也可以从外接对这个转换进行额外的操作。

 

0 0
原创粉丝点击