Qt 的Graphics View框架

来源:互联网 发布:mac怎么设置开机密码 编辑:程序博客网 时间:2024/05/22 06:34
Graphics View 框架
一直一来,对Graphics View框架都没进行系统的学习和总结,今天就来梳理一下。
Graphics View框架提供基于图元的模型-视图编程,它包括三个主要的类:QGraphicsScene, QGraphicsView,
QGraphicsItem,分别是场景、视图和图元。一个场景可以通过多个视图表现,一个场景可以包括多个几何图形。
1、场景:
场景类完成如下功能:
* 提供管理大量图元的快速接口
* 传播事件给场景中的每个图元
* 管理图元状态,如选择和焦点处理
* 提供无变换的绘制功能,如打印
    场景是QGraphicsItem对象的容器,QGraphicsScene::addItem().图元可以通过多个函数进行检索:QGraphicsScene::items()
和一些重载函数可以返回和点、矩形、多边形或向量路径相交的所有图元,QGraphicsScene::itemAt()返回指定点的最顶层图元。
QGraphicsScene的事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播。如果场景接收到了在某一点的鼠标单击
事件,场景将会把事件传给在这一点的最顶层图元。QGraphicsScene负责管理一些图元的状态,如图元选择和焦点。通过
QGraphicsScene::setSelectionArea()选择图元,选择区域可以是任意形状,使用QPainterPath表示;得到当前选择的图元列表:
QGraphicsScene::selectedItems().QGraphicsScene::setFocusItem()或QGraphicsScene::setFocus()来设置图元的焦点;
获得当前具有焦点的图元:QGraphicsScene::focusItem();
    使用QGraphicsScene::render()在特定的绘图设备上绘制场景。
2、视图:
    QGraphicsView是视图窗口控件, 它使场景的内容可视化。可以连接几个视图到一个场景,也可以为相同的数据集提供几种不同的视口,
QGraphicsView是可滚动的窗口部件,如果需要使用OpenGL,使用QGrphicsView::setViewPort()将视口设置为QGLWidget。
    视图接收键盘和鼠标的输入事件,并把它翻译为场景事件(将坐标转换为场景的坐标),使用变换矩阵函数QGraphicsView::matrix()
可以变换场景的坐标,通过这种方法尅实现场景缩放和旋转。QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()将
视图和场景的坐标进行转换。
3、图元:
    QGraphicsItem是图元基类,QGraphics View框架提供了几种标准的图元,如QGraphicsRectItem、QGraphicsEllipseItem,
QGraphicsTextItem等,可以继承QGraphicsItem实现符合自己需要的图元。
    QGraphicsItem功能:
* 处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件;
* 处理键盘输入事件;
* 处理拖放事件;
* 分组;
* 碰撞检测。
    图元有自己的坐标系统,有场景和图元、图元和图元之间的坐标转换函数。图元可通过QGraphicsItem::matrix()来进行自身变换。
图元可包含子图元。
坐标:
    图元中心为图元坐标原点,xy右下;场景坐标描述了顶层的图元,每个图元都有场景坐标和响应的包容框,场景中心为原点,xy右下;
视图坐标是窗口部件的坐标,即左上角(0,0),xy右下,所有鼠标事件刚开始使用的都是视图坐标。
坐标映射:
    QGraphicsView::mapToScene();
    QGraphicsView::mapFromScene();
    QGraphicsItem::mapFromScene();
    QGraphicsItem::mapToScene();
    QGraphicsItem::mapFromParent();
    QGraphicsItem::mapToParent();
    QGraphicsItem::mapToItem();
    QGraphicsItem::mapFromItem();
/************************************************************************************************************/
1、缩放和旋转
    QGraphicsView::setMatrix()支持同QPainter一样的几何变换,当进行视图变换时,QGraphicsView保持视图的中心。
     matrix(), setTransform(), rotate(), scale(), shear(), and translate().
class View: public QGraphicsView{
    Q_OBJECT
    ...
public slots:
    void  zoomIn() { scale(1.5,1.5); }
    void  zoomOut() { scale(1/1.5,1/1.5); }
    void  rotateLeft() { rotate(-90); }
    void  rotateRight() { rotate(90); }
    ...
};
//将槽和具有autoRepeat属性的QToolButton进行连接,就可实现连续的缩放操作。
2、光标和工具提示
    QGraphicsView::setCursor(),QGraphicsView::setToolTip();
3、动画
    可以将动画路径通过QGraphicsItemAnimation和图元关联,这可以使时间线性控制的图元在所有平台上速度一致。
QGraphicsItemAnimation允许创建图元的路径,包括位置、旋转、缩放、扭曲、平移等操作的路径,即在不同时候进行
不同的变换。动画通常用QTimeLine控制,也可使用QSlider控制。
    也可以创建从QObject和QGraphicsItem继承的图元,此类图元可以自己设置自己的定时器,通过QObject::timerEvent()
来控制动画。
//模拟太阳升起落下的过程:
#include <QtGui>
#include <cmath>
using namespace std;
const qreal PI = 3.1415926;
int main(int argc, char *argv[]){
    QApplication app(argc,argv);
    QGraphicsEllipseItem *sun = new QGraphicsEllipseItem(0,0,20,20);
    sun->setBrush(Qt::red);
    sun->setPen(QPen(Qt::red));
    QTimeLine *timeLine = new QTimeLine(10000);
    timeLine->setCurveShape(QTimeLine::LinearCurve);
    QGraphicsItemAnimation *animation = new QGraphicsItemAnimaion;
    animation->setItem(sun);
    animation->setTimeLine(timeLine);
    qreal x,y;
    qreal angle = PI;
    for(int i = 0; i <= 180; ++i){
        x = 200.0 * cos(angle);
        y = 200.0 * sin(angle);
        animation->setPosAt(i/180.0,QPointF(x,y)); //分180步
        angle += PI/180.0
    }
    QGraphicsScene *scene = new QGraphicsScene();
    scene->addItem(sun);
    QGraphicsView *view = new QGraphicsView(scene);
    view->resize(640,480);
    view->show();
    timeLine->start();
    return app.exec();
}
4、OpenGL绘制
    要使用OpenGL绘制,可以调用QGraphicsView::setViewPort()来设置QGLWidget作为
QGraphicsView的视口。如果需要在OpenGL中打开反锯齿,使用QGLFormat::sampleBuffers()
来使用OpenGL的采样缓冲区。
5、图元组
    使用图元组可以将图元组合在一起,对图元组的变换对所有子图元都有效。QGraphicsItem可以处理
所有子图元的事件: GraphicsItem::setHandlesChildEvents().
  //若从QGraphicsItem继承,因为是抽象基类,所以至少要实现两个纯虚函数boundingRect()和paint().
                                             
0 0