现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

Qt的Graphics View框架

2011-01-13 23:05 工业·编程 ⁄ 共 5784字 ⁄ 字号 暂无评论

Qt4.2开始引入了Graphics View框架用来取代Qt3中的Canvas模块,并在很多地方作了改进,Graphics View框架实现了模型-视图结构的图形管理,能对大量图元进行管理,支持碰撞检测,坐标变换和图元组等多种方便的功能。GraphicsView中增强的表现系统可以利用Qt4绘图系统的反锯齿,OpenGL工具来改善绘图性能,Graphics View支持事件传播体系结构,可以利用图元在场景(scene)中的到提高了一倍的精确交互能力,图元能够处理键盘事件,鼠标按下,移动,释放,双击事件,也能跟踪鼠标的移动,在Graphics View框架中,通过BSP(二元空间划分树)来提供快速的图元查找.这样就能实时地显示大场景,甚至上百万个图元。GraphicsView框架提供基于图元的视图-模型编程,类似于QtInterView的模型,视图结构,只是这里的数据是图形,Graphics View框架中包含三个主要的类,QGraphicsScene,QGraphicsView,QGraphicsItem,分别是场景,视图和图元。一个场景可以通过多个视图表现,一个场景中包括多个几何图形。

---------------------------

1 场景QGraphicsScene

QGraphicsScene类实现QGraphics View中的场景,场景类完成如下功能:

提供管理大量图元的快速接口

传播事件给场景中的每个图元

管理图元状态,如选择焦点处理

提供无变换的绘制功能,如打印

场景是QGraphicsItem对象的容器,通过函数QGraphicsScene::addItem()可以加入一个图元到场景中,图元可以通过多个函数进行检索,QGraphicsScene::items()和一些重载的函数可以返回点,矩形,多边形或向量路径相交的所有图元,QGraphicsScene::itemAt()返回指定点的顶层图元。QGraphicsScene的事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播,如果场景收到了某一点的鼠标单击事件,场景会把事件传给在这一点的图元。QGraphicsScene负责管理一些图元的状态,如图元选择和焦点。可以通过QGraphicsScene::setSeletionArea()函数选择图元,选择区域可以是任意的形状,使用QPainterPath表示,要得到当前选择的图元列表可以使用QGraphicsScene::selectedItems().QGraphicsScene还管理图元的键盘输入焦点状态,可以通过QGraphicsScene::setFocusItem()函数或者QGraphicsItem::setFoucs()函数来设置图元的焦点,获得当前具有焦点的图元使用函数QGraphicsScene::foucsItem().如果需要在场景内绘制到特定的绘图设备,可以使用QGraphicsScene::render()函数在绘图设备上绘制场景。

2 视图

QGraphics View是视图窗口部件,他使场景内容可视化,可以连接几个视图到一个场景,也可以为相同的数据源的数据集提供集中不同的视口。QGraphicsView是可滚动的窗口部件,可以提供滚动条来浏览大的场景。如果需要使用OpenGL,可以使用QGraphicsView::setViewport()将适口设置为QGLWidget.视图接收键盘和鼠标的输入事件,并把它翻译为场景事件。(将坐标转换为场景的坐标)。使用变换矩阵函数QGraphicsView::martix可以变换场景的坐标。通过这种方法可以实现场景的缩放和旋转。QGraphicsView提供QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()来和场景的坐标进行转换。

3 图元

QGraphicsItem是图元的基类。QGraphics View框架提供了几种标准的图元。矩形(QGraphicsRectItem),椭圆(QGraphcisEllipseItem),文本图元(QGraphicsTextItem)等。用户可以继承QGraphicItem实现符合自己的图元。QGraphicsItem具有下列功能:

处理鼠标按下,移动,释放,双击,悬停,滚动和右键菜单事件。

处理键盘输入事件

处理拖放事件 分组: 碰撞检测

图元有自己的坐标系统,也提供场景和图元。图元和图元之间的坐标变换函数,图元也可以通过QGraphicsItem::martix()来进行自身的变换。图元可以包含子图元。

Graphics View坐标系统

Graphics View坐标系基于笛卡尔坐标系,一个图元的场景坐标具有x坐标和y坐标。当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素。在Graphics View中有三个有效的坐标系统,图元坐标,场景坐标,和视图坐标。Graphics View提供了三个坐标系统之间的转换函数。在绘制图形所时,QGraphics View的场景坐标对应QPainter的逻辑坐标,视图坐标和设备坐标相同。

1 图元坐标

图元使用自己的本地坐标,这个坐标系统通常以图元中心为原点,这也是所有坐标变换的原点,图元坐标方向是x轴正方向向右。y轴正方向下。创建图元后,之需要注意图元的坐标就可以了。QGraphicsScene和QGraphicsView会完成所有的变换。

2 场景坐标

场景坐标是所有图元的基础坐标系统。场景坐标系统描述了顶层图元。每个图元都有场景坐标和相应的包容框,场景坐标的原点在场景中心.

3 视图坐标

视图坐标是窗口部件的坐标,视图坐标的单位是像素,QGraphicsView的左上角是(0,0).所有鼠标事件最开始都使用视图坐标。

4 坐标映射

在Graphics View框架中,经常需要将多种坐标变换,从场景到图元,从图元到图元,从视图到场景 QGraphics View框架坐标变换函数

QGraphicsView::mapToScene()

QGraphicsView::mapFromScene()

QGraphicsItem::mapFromScene()

QGraphicsItem::mapToScene()

QGraphicsItem::mapToParent()

QGraphicsItem::mapFromParent();

QGraphicsItem::mapToItem();

QGraphicsItem::mapFromItem();

-------------------------------------------------- -----------------------

深入 QGraphics View

1 缩放和旋转

GraphicsView通过QGraphicsView::setMartix()支持同QPainter一样的几何变换。当进行视图变换时,QGraphicsView保持视图中心。通过应用变换,可以很容易实现缩放和旋转。 下面说明如何通过缩放和旋转槽来实现对视图的缩放和旋转。

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 光标和和工具提示

和QWidget一样,QGraphicsItem支持图元特定的光标(应用QGraphicsItem::setCursor())和工具提示(QGraphicsItem::setToolTip()).在鼠标进入图元区域时激活相应的光标和工具提示。

3 动画

QGraphics View支持几种不同级别的动画,可以将动画路径通过QGraphicsItemAnimation和图元关联。这是一使时间线性控制的图元在所有平台上的速度一致。QGraphcisItemAnimation允许创建图元的路径,包括位置,旋转,缩放,扭曲,平移等操作的路径。即在不同的时候进行不同的变换。动画通过常用QTimeLine来控制,也可以用QSlider来控制。也可以创建从QObject和QGraphicsItem继承的图元,此类图元可以设置自己的定时器,通过QObject::timeEvent()来控制动画。

4 OpenGL绘制

要使用OpenGL绘制,可以调用QGraphicsView::setViewport()来设置QGLWidget作为QGraphicsView的视口,如果需要在OpenGL中打开反锯齿,可以使用QGLFormat::sampleBuffer()来使用OpenGL的采用缓冲区(samplebuffer);

5 图元组

使用图元组可以将图元组合在一起,对图元组的变换对所有子图元都有效,QGraphpicsItem莪可以处理所有子图元的事件(使用QGraphicsItem::setHandlesChildEvents()),即允许组合图元处理所有子图元的事件。

6.8 图形图像的打印

Qt提供了夸平台的打印支持,能够使用本地和远程的打印机,Qt的打印系统甚至支持直接生成PostScript可PDF文件,QPrinter类对打印机进行了抽象,他实际上时支持打印的特殊绘图设备(QPainteDevice).QPrinter支持多页和双面打印,使用QPrinter可以和绘制自定义的窗口一样完成打印操作。

普通打印过程。

QPrinter printer;

QPrintDialog *dialog=new QPrintDialog(&printer,this);

dialog->setWindowTitle(tr("打印文档"));

if(dialog->exec()!=QDialog::Accepted) return ; 创建了打印设备后及时对打印设备的设置,然后就开始打印 QPainter painter;

painter.begin(&printer);

for(int page=0;page<numberofPages;++page) {

if(page!=lastPage) printer.newPage();

}

painter.end(); paperRect()获取纸张尺寸,pageRect()获取可打印的区域大小

void MainWindow::print() {

QPrinter printer;

QPrintDialog dialog(&printer,this);

if(dialog.exec()) {

QPainter painter(&printer);

QRect rect=painter.viewport();

QSize size=imageWidget->size();

size.scale(rect.size(),Qt::KeepAspectRatio);

painter.setViewport(rect.x(),rect.y(),size.width() ,size.height());

painter.setWindow(imageWidget->rect());

painter.drawPixmap(0,0,QPixmap::grabWidget(imageWi dget,imageWidget->rect()));

}

}

程序将窗口部件上的俄图形用grabWidget()函数抓取到QPixmap对象中,然后直接将QPixmap对象绘制到打印机上。 特殊窗口部件的打印 一些特殊窗口部件的绘制功能是由相应的内容管理类进行管理。如QTextEdit和QGraphicsView显示的内容分别由QTextDocument和QGraphicsScene类管理。对于这些类,他们的打印功能由内容管理类或特定的函数完成。

这些类如图

--------------------------------------------------

QGraphicsView QGraphicsView::render();

QSvgWidget QSvgRenderer::render();

QTextEdit QTextDocument::print();

QTextLayout QTextLayout::draw();

QTextLine QTextLine::draw()

--------------------------------------------------

Graphics View框架通过场景QGraphicsScene::render()函数和视图的QGraphicsView::render()函数结合就可以完成打印工作。这两个函数将场景和视图上的内容全部打印到任意绘图设备。 场景和视图绘制函数的差别就在于一个使用场景坐标,一个使用视图坐标,QGraphicsScene::render()通常用来绘制没有变换的场景,如几何数据,文本文档,QGraphicsView::render()则用来实现屏幕快照,他默认的行为是将视口的数据绘制到指定的绘图所设备。当源区域和目标区域大小不相同时,源区域将会按指定的内容缩放以符合目标区域,缩放比例取决于Qt::AspectRadioMode.

void MainWindow::print() {

QPrinter printer;

if(QPrintDialog(&printer).exec()==QDialog::Accepte d)

{

QPainter painter(&printer);

painter.setRenderHint(QPainter::Antialiasing);

scene->render(&painter);

}

}

用户可以将上面的scene->render(&painter)换为view->render(&painter).

给我留言

留言无头像?