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).