赞
踩
Graphics View(图形视图)框架结构取代了之前Qt版本中的QCanvas模块,它提供了基于图元的模型/视图编程,类似于QtInterView的模型/视图结果,只是这里的数据是图形。
Graphics View框架结构的特点主要包含元素及坐标系统。
Graphics View框架结构的主要特点如下:
Graphics View框架结构主要包含三个类:场景类(QGraphicsScene)、视图类(QGraphicsView)和图元类(QGraphicsItem),统称为“三元素”。其中,场景类提供了一个用于管理位于其中的众多图元容器,视图类用于显示场景中的图元,一个场景可以通过多个视图表现,一个场景包括多个几何图形。它们三者这间关系如下:
场景类:QGraphicsScene类
这是一个用于放置图元的容器,本身是不可见的,必须通过与之相连的视图类来显示及与外界进行互操作。通过 QGraphicsScene::addItem()可以添加一个图元到场景中。图元可以通过多个函数进行检索。QGraphicsScene::items()和一些重载函数可以返回和点、矩形、多边形或向量路径相交的所有图元。QGraphicsScene::itemAt()返回指定点的顶层图元。
场景类主要完成的工作包括提供对它包含的图元的操作接口和传递事件、管理各个图元的状态(如选择和焦点处理)、提供无变换的绘制功能(如打印)等。
事件传播体系结构将场景事件发送给图元,同时管理图元之间的事件传递。如果场景接收到了在某一点的鼠标单击事件,场景会将事件传给这一点的图元。
管理各个图元的状态(如选择和焦点处理)。可以通过QGraphicsScene::setSelectionArea()函数旋转图元,选择区域可以是任意的形状,使用QPainterPath表示。若要得到当前选择的图元列表,则可以使用函数QGraphicsScene::selectedItems()。可以通过QGraphicsScene::setFocusItem()函数或QGraphicsScene::setFocus()函数来设置图元的焦点,获得当前具有焦点的图元使用函数QGraphicsScene::focusItem()。
如果需要将场景内容绘制到特定的绘图设备,则可以使用QGraphicsScene::render()函数在绘图设备上绘制场景。
视图类:QGraphicsView类
它提供一个可视的窗口,用于显示场景的图元。在同一个场景中可以有多个视图,也可以为相同的数据提供几种不同的视图。
QGraphicsView是可滚动的窗口部件,可以提供滚动条来浏览大的场景。如果需要使用OpenGL,则可以使用QGraphicsView::setViewport()将视图设置成为QGLWideget。
视图接收键盘和鼠标的输入事件,并将它们翻译为场景事件(将坐标转换为场景的坐标)。使用变换矩阵函数QGraphicsView::matrix()可以变换场景的坐标,实现场景的缩放和旋转。QGraphicsView提供QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()用于与场景的坐标进行转换。
图元类:QGraphicsItem类
它是场景中各个图元的基类,在它的基础上可以继承出各种图元类,Qt已经预置的包括直线(QGraphicsLineItem)、椭圆(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。当然,也可以在QGraphicsItem类的基础上实现自定义的图元类。用户可以继承QGraphicsItem实现符合自己需要的图元。
图元有自己的坐标系,也提供场景和图元。图元还可以通过QGraphicsItem::matrix()来进行自身的变换,可以包含子图元。
QGraphicsItem主要有以下功能:
QGraphicsView坐标基于笛卡尔坐标系,一个图元的场景具有x坐标和y坐标。当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素。
三个Graphics View基本类有各自不同的坐标系,场景坐标、视图坐标和图元坐标。Graphics View提供了三个坐标系统之间的转换函数。在绘制图形时,Graphics View的场景坐标对应QPainter的逻辑坐标、视图坐标和设备坐标。
根据需要,Qt提供了这三个坐标系之间的互相转换函数,以及图元与图元之间的转换函数,若需要从QGraphicsItem坐标系中的某一点坐标转换到场景中的坐标,则可调用QGraphicsItem的mapToScene()函数进行映射。而QGraphicsItem的mapToParent()函数则可将QGraphicsItem坐标系中的某点坐标映射到它的上一级坐标系中,有可能是场景坐标,也可能是另一个QGraphicsItem坐标。
Graphics View框架提供了多种坐标变换函数。如下:
映射函数 | 转换类型 |
---|---|
QGraphicsView::mapToScene | 视图到场景 |
QGraphicsView::mapFromScene | 场景到视图 |
QGraphicsItem::mapFromScene | 场景到图元 |
QGraphicsItem::mapToScene | 图元到场景 |
QGraphicsItem::mapToParent | 子图元到父图元 |
QGraphicsItem::mapRectFromParent | 父图元到子图元 |
QGraphicsItem::mapToItem | 本图元到其他图元 |
QGraphicsItem::mapRectFromItem | 其他图元到本图元 |
同示例介绍如何进行自定义QGraphicsItem,以及如何通过利用定时器来实现QGraphicsItem动画效果。
设计界面,一个蝴蝶在屏幕上不停地上下飞舞。
#ifndef BUTTERFLY_H #define BUTTERFLY_H #include <QObject> #include <QGraphicsItem> #include <QPainter> #include <QGraphicsScene> #include <QGraphicsView> class Butterfly : public QObject, public QGraphicsItem { Q_OBJECT public: explicit Butterfly(QObject *parent = nullptr); void timerEvent(QTimerEvent *event);//定时器实现动画的原理是在定时器的timerEvent()中对QGraphicsItem进行重绘 QRectF boundingRect()const;//为图元限定区域范围,所有继承自QGraphicsItem的自定义图元都必须实现此函数 signals: public slots: protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);//重绘函数 private: bool up; QPixmap pix_up; QPixmap pix_down; qreal angle; }; #endif // BUTTERFLY_H
#include "butterfly.h" #include <math.h> const static double PI = 3.1416; Butterfly::Butterfly(QObject *parent) : QObject(parent) { up = true;//标志蝴蝶翅膀位置的变量赋初值 pix_up.load("up.png");//加载图片 pix_down.load("down.png"); startTimer(100); } QRectF Butterfly::boundingRect() const { qreal adjust = 2; return QRectF(-pix_up.width()/2 - adjust, -pix_up.height()/2-adjust, pix_up.width() + adjust*2, pix_up.height() + adjust*2); } void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if(up) { painter->drawPixmap(boundingRect().topLeft(), pix_up); up = !up; } else{ painter->drawPixmap(boundingRect().topLeft(), pix_down); up = !up; } } void Butterfly::timerEvent(QTimerEvent *event) { //边界控制 qreal edgex = scene()->sceneRect().right() + boundingRect().width() / 2;//限定蝴蝶飞舞的右边界 qreal edgetop = scene()->sceneRect().top() + boundingRect().height() / 2;//限定蝴蝶飞舞的上边界 qreal edgebottom = scene()->sceneRect().bottom() + boundingRect().height() / 2;//限定蝴蝶飞舞的下边界 if(pos().x() >= edgex)//超过右边界,水平回到最左边 setPos(scene()->sceneRect().left(), pos().y()); if(pos().y() <= edgetop)//超过上边界,回到底边 setPos(pos().x(), scene()->sceneRect().bottom()); if(pos().y() >= edgebottom)//超过底边,回到上边界 setPos(pos().x(), scene()->sceneRect().top()); angle += (qrand() % 10) / 20.0; qreal dx = fabs(sin(angle * PI) * 10.0); qreal dy = fabs(qrand()%20) - 10.0; setPos(mapToParent(dx, dy));//完成飞行路径。 }
#include "mainwindow.h" #include <QApplication> #include <QGraphicsScene> #include "butterfly.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QGraphicsScene *scene = new QGraphicsScene; scene->setSceneRect(QRectF(-200, -200, 400, 400)); Butterfly *butterfly = new Butterfly; butterfly->setPos(-100, 0); scene->addItem(butterfly); QGraphicsView *view = new QGraphicsView; view->setScene(scene); view->resize(400, 400); view->show(); // MainWindow w; // w.show(); return a.exec(); }
实现一个地图浏览器的基本功能,来介绍使用Graphics View框架。
#ifndef MAPWIDGET_H #define MAPWIDGET_H #include <QObject> #include <QGraphicsView> #include <QMouseEvent> #include <QLabel> class MapWidget : public QGraphicsView { Q_OBJECT public: MapWidget(); void readMap();//读取地图信息 QPointF mapToMap(QPointF);//用于实现场景坐标系与地图坐标之间的映射,以获得某点的经纬度值。 public slots: void slotZoom(int); protected: void drawBackground(QPainter *painter, const QRectF &rect);//完成地图显示功能 void mouseMoveEvent(QMouseEvent *event); private: QPixmap map; qreal zoom; QLabel *viewCoord; QLabel *sceneCoord; QLabel *mapCoord; double x1, y1; double x2, y2; }; #endif // MAPWIDGET_H
#include "mapwidget.h" #include <QSlider> #include <QGridLayout> #include <QFile> #include <QTextStream> #include <QGraphicsScene> #include <math.h> MapWidget::MapWidget() { //读取地图信息 readMap();//用于读取描述地图信息的文件 zoom = 50; int width = map.width(); int height = map.height(); QGraphicsScene *scene = new QGraphicsScene(this);//新建一个对象为主窗口连接一个场景 //限定场景的显示区域为地图的大小 scene->setSceneRect(-width/2, -height/2, width, height); setScene(scene); setCacheMode(CacheBackground); //用于地图缩放的滑动条 QSlider *slider = new QSlider; slider->setOrientation(Qt::Vertical); slider->setRange(1, 100); slider->setTickInterval(10); slider->setValue(50); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(slotZoom(int))); QLabel *zoominLabel = new QLabel; zoominLabel->setScaledContents(true); zoominLabel->setPixmap(QPixmap("zoomin.png")); QLabel *zoomoutLabel = new QLabel; zoomoutLabel->setScaledContents(true); zoomoutLabel->setPixmap(QPixmap("zoomout.png")); //坐标值显示区 QLabel *label1 = new QLabel(tr("GraphicsView:")); viewCoord = new QLabel; QLabel *label2 = new QLabel(tr("GraphicsScene:")); sceneCoord = new QLabel; QLabel *label3 = new QLabel(tr("map:")); mapCoord = new QLabel; //坐标显示区布局 QGridLayout *gridLayout = new QGridLayout; gridLayout->addWidget(label1, 0, 0); gridLayout->addWidget(viewCoord, 0, 1); gridLayout->addWidget(label2, 1, 0); gridLayout->addWidget(sceneCoord, 1, 1); gridLayout->addWidget(label3, 2, 0); gridLayout->addWidget(mapCoord, 2, 1); gridLayout->setSizeConstraint(QLayout::SetFixedSize); QFrame *coordFrame = new QFrame; coordFrame->setLayout(gridLayout); //缩放控制子布局 QVBoxLayout *zoomLayout = new QVBoxLayout; zoomLayout->addWidget(zoominLabel); zoomLayout->addWidget(slider); zoomLayout->addWidget(zoomoutLabel); //坐标显示区域布局 QVBoxLayout *coordLayout = new QVBoxLayout; coordLayout->addWidget(coordFrame); coordLayout->addStretch(); //主布局 QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(zoomLayout); mainLayout->addLayout(coordLayout); mainLayout->addStretch(); mainLayout->setMargin(30); mainLayout->setSpacing(10); setLayout(mainLayout); setWindowTitle(tr("Map Widget")); setMinimumSize(600, 400); } void MapWidget::readMap() { QString mapName; QFile mapFile("maps.text");//新建一个QFile对象, 描述地图信息文本 int ok = mapFile.open(QIODevice::ReadOnly);//以只读方式打开文件 if(ok) { QTextStream ts(&mapFile); if(!ts.atEnd()) { ts >> mapName; ts >> x1 >> y1 >> x2 >> y2; } } map.load(mapName);//将地图读取到私有变量map中。 } void MapWidget::slotZoom(int value) { qreal s; if(value > zoom) {//放大 s = pow(1.01, (value - zoom)); } else {//缩小 s = pow(1/1.01, (zoom - value)); } scale(s, s); zoom = value; } void MapWidget::drawBackground(QPainter *painter, const QRectF &rect) { painter->drawPixmap(int(sceneRect().left()), int(sceneRect().top()), map); } void MapWidget::mouseMoveEvent(QMouseEvent *event) { //QGraphicsView坐标 QPoint viewPoint = event->pos(); viewCoord->setText(QString::number(viewPoint.x()) + "," + QString::number(viewPoint.y())); //QGraphicsScene坐标 QPointF scenePoint = mapToScene(viewPoint); sceneCoord->setText(QString::number(scenePoint.x()) + "," + QString::number(scenePoint.y())); //地图坐标 QPointF latLon = mapToMap(scenePoint); mapCoord->setText(QString::number(latLon.x()) + "," + QString::number(latLon.y())); } QPointF MapWidget::mapToMap(QPointF p) { QPointF latLon; qreal w = sceneRect().width(); qreal h = sceneRect().height(); qreal lon = y1 - ((h/2 + p.y()) * abs(y1 - y2)/h); qreal lat = x1 + ((w/2 + p.x()) + abs(x1 - x2)/w); latLon.setX(lat); latLon.setY(lon); return latLon; }
#include "mainwindow.h" #include <QApplication> #include "mapwidget.h" #include <QFont> int main(int argc, char *argv[]) { QApplication a(argc, argv); QFont font("ARPL KaitiM GB", 12); font.setBold(true); a.setFont(font); MapWidget mapWidget; mapWidget.show(); // MainWindow w; // w.show(); return a.exec(); }
通过一个示例来演示各个图元的创建。代码结构如下:
具体代码如下:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsScene> #include <QGraphicsView> #include <QMenuBar> #include <QGraphicsEllipseItem> #include "flashitem.h" #include "startitem.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); //初始化场景 void initScene(); //创建主窗体的所有动作 void createActions(); //创建主窗体的菜单栏 void createMenus(); public slots: void slotNew();//新建显示窗体 void slotClear();//清除场景中所有的图元 void slotAddEllipseItem();//添加一个椭圆形图元 void slotAddPolygonItem();//添加一个多边形图元 void slotAddTextItem(); //在场景中加入一个文字图元 void slotAddRectItem(); //在场景中加入一个长方形图元 void slotAddAlphaItem(); //在场景中加入一个透明蝴蝶图片 void slotAddFlashItem();//添加flash图元 void slotAddAnimationItem();//添加动画图元 private: QGraphicsScene *scene; QAction *newAct; QAction *clearAct; QAction *exitAct; QAction *addEllipseItemAct; QAction *addPolygonItemAct; QAction *addTextItemAct; QAction *addRectItemAct; QAction *addAlphaItemAct; QAction *addFlashItemAct; QAction *addAnimItemAct; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include <QGraphicsItemAnimation> #include <QTimeLine> #include <QList> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { //创建主窗体的所有动作 createActions(); //创建主窗体的菜单栏 createMenus(); scene = new QGraphicsScene; scene->setSceneRect(-200, -200, 400, 400); //初始化场景 initScene(); QGraphicsView *view = new QGraphicsView; view->setScene(scene); view->setMinimumSize(400, 400); view->show(); setCentralWidget(view); resize(550, 450); setWindowTitle(tr("Graphics Items")); } MainWindow::~MainWindow() { } void MainWindow::createActions() { //创建主窗体的所有动作 newAct = new QAction(tr("新建"), this); clearAct = new QAction(tr("清除"), this); exitAct = new QAction(tr("退出"), this); addEllipseItemAct = new QAction(tr("加入 椭圆"),this); addPolygonItemAct = new QAction(tr("加入 多边形"),this); addTextItemAct = new QAction(tr("加入 文字"),this); addRectItemAct = new QAction(tr("加入 长方形"),this); addAlphaItemAct = new QAction(tr("加入 图片"),this); connect(newAct,SIGNAL(triggered()),this,SLOT(slotNew())); connect(clearAct,SIGNAL(triggered()),this,SLOT(slotClear())); connect(exitAct,SIGNAL(triggered()),this,SLOT(close())); connect(addEllipseItemAct,SIGNAL(triggered()),this,SLOT (slotAddEllipseItem())); connect(addPolygonItemAct,SIGNAL(triggered()),this,SLOT (slotAddPolygonItem())); connect(addTextItemAct,SIGNAL(triggered()),this,SLOT (slotAddTextItem())); connect(addRectItemAct,SIGNAL(triggered()),this,SLOT (slotAddRectItem())); connect(addAlphaItemAct,SIGNAL(triggered()),this,SLOT (slotAddAlphaItem())); addFlashItemAct = new QAction(tr("加入闪烁圆"),this); connect(addFlashItemAct,SIGNAL(triggered()),this,SLOT(slotAddFlashItem())); addAnimItemAct = new QAction(tr("加入 移动星星"),this); connect(addAnimItemAct,SIGNAL(triggered()),this,SLOT(slotAddAnimationItem())); } void MainWindow::createMenus() { QMenu *fileMenu = menuBar()->addMenu(tr("文件")); fileMenu->addAction(newAct); fileMenu->addAction(clearAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct); QMenu *itemMenu = menuBar()->addMenu(tr("元素")); itemMenu->addAction(addEllipseItemAct); itemMenu->addAction(addPolygonItemAct); itemMenu->addAction(addTextItemAct); itemMenu->addAction(addRectItemAct); itemMenu->addAction(addAlphaItemAct); itemMenu->addAction(addFlashItemAct); itemMenu->addAction(addAnimItemAct); } void MainWindow::initScene() { //初始化场景 for(int i = 0; i < 3; i++) slotAddEllipseItem(); for(int i = 0; i < 3; i++) slotAddPolygonItem(); for(int i = 0; i < 3; i++) slotAddTextItem(); for(int i = 0; i < 3; i++) slotAddRectItem(); for(int i = 0; i < 3; i++) slotAddAlphaItem(); for(int i = 0; i < 3; i++) slotAddFlashItem(); for(int i = 0; i < 3; i++) slotAddAnimationItem(); } void MainWindow::slotNew() { //新建一个显示窗体 slotClear(); initScene(); MainWindow *newWin = new MainWindow; newWin->show(); } void MainWindow::slotClear() { //清除场景中的所有图元 QList<QGraphicsItem*> listItem = scene->items(); while(!listItem.empty()) { scene->removeItem(listItem.at(0)); listItem.removeAt(0); } } void MainWindow::slotAddEllipseItem() { //在场景中加入椭圆形图元 QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 80, 60)); item->setPen(Qt::NoPen); item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); item->setFlag(QGraphicsItem::ItemIsMovable); scene->addItem(item); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddPolygonItem() { QVector<QPoint> v; v << QPoint(30, -15) << QPoint(0, -30) << QPoint(-30, -15) << QPoint(-30, 15) << QPoint(0, 30) << QPoint(30, 15); QGraphicsPolygonItem *item = new QGraphicsPolygonItem(QPolygonF(v)); item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); item->setFlag(QGraphicsItem::ItemIsMovable); scene->addItem(item); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddTextItem() { //在场景中添加一个文字图元 QFont font("Times", 16); QGraphicsTextItem *item = new QGraphicsTextItem("Hello Qt!"); item->setFont(font); item->setFlag(QGraphicsItem::ItemIsMovable); item->setDefaultTextColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); scene->addItem(item); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddRectItem() { //添加长方形图元 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 60, 60)); QPen pen; pen.setColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); item->setPen(pen); item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); item->setFlag(QGraphicsItem::ItemIsMovable); scene->addItem(item); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddAlphaItem() { //添加一个透明蝴蝶图片 QGraphicsPixmapItem *item = scene->addPixmap(QPixmap("image.png")); item->setFlag(QGraphicsItem::ItemIsMovable); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddFlashItem() { //添加闪烁图元 FlashItem *item = new FlashItem; scene->addItem(item); item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200); } void MainWindow::slotAddAnimationItem() { //添加动画星星 StartItem *item = new StartItem; QGraphicsItemAnimation *anim = new QGraphicsItemAnimation; anim->setItem(item); QTimeLine *timeLine = new QTimeLine(4000); timeLine->setCurveShape(QTimeLine::SineCurve); timeLine->setLoopCount(0); anim->setTimeLine(timeLine); int y = (qrand() % 400) - 200; for(int i = 0; i < 400; i++) { anim->setPosAt(i/400.0, QPointF(i-200, y)); } timeLine->start(); scene->addItem(item); }
#ifndef STARTITEM_H #define STARTITEM_H #include <QGraphicsItem> #include <QPainter> class StartItem : public QGraphicsItem { public: StartItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr); private: QPixmap pix; }; #endif // STARTITEM_H
#include "startitem.h" StartItem::StartItem() { pix.load("start.png"); } QRectF StartItem::boundingRect() const { return QRectF(-pix.width()/2, -pix.height()/2, pix.width(), pix.height()); } void StartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->drawPixmap(boundingRect().topLeft(), pix); }
#ifndef FLASHITEM_H #define FLASHITEM_H #include <QObject> #include <QGraphicsItem> #include <QPainter> #include <QTimer> class FlashItem : public QObject, public QGraphicsItem { Q_OBJECT public: explicit FlashItem(QObject *parent = 0); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr); void timerEvent(QTimerEvent *event); private: bool flash; QTimer *timer; }; #endif // FLASHITEM_H
#include "flashitem.h" FlashItem::FlashItem(QObject *parent) { flash = true;//为颜色切换标识。 setFlag(ItemIsMovable); startTimer(1000);//启动定时器 } QRectF FlashItem::boundingRect() const { qreal adjust = 2; return QRectF(-10-adjust, -10-adjust, 43 + adjust, 43 + adjust); } void FlashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->setPen(Qt::NoPen); painter->setBrush(Qt::darkGray);//深灰色 painter->drawEllipse(-7, -7, 40, 40); painter->setPen(QPen(Qt::black, 0)); //闪烁区边线为黑色 painter->setBrush(flash ? (Qt::red) : (Qt::yellow)); painter->drawEllipse(-10, -10, 40, 40); } void FlashItem::timerEvent(QTimerEvent *event) { flash = !flash; update(); }
通过实现一个示例演示将图元进行旋转、缩放、切变和位移
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
#ifndef MAINWIDGET_H #define MAINWIDGET_H #include <QWidget> #include <QGraphicsView> #include <QGraphicsScene> #include <QFrame> #include "pixitem.h" class MainWidget : public QWidget { Q_OBJECT public: MainWidget(QWidget *parent = 0); ~MainWidget(); void createControlFrame(); private: int angle; qreal scaleValue; qreal shearValue; qreal translateValue; QGraphicsView *view; QFrame *ctrlFrame; PixItem *pixItem; public slots: void slotRotate(int); void slotScale(int); void slotShear(int); void slotTranslate(int); }; #endif // MAINWIDGET_H
#include "mainwidget.h" #include <QHBoxLayout> #include <QVBoxLayout> #include <QSlider> #include <QGroupBox> #include <math.h> MainWidget::MainWidget(QWidget *parent) : QWidget(parent) { angle = 0; scaleValue = 5; shearValue = 5; translateValue = 50; QGraphicsScene *scene = new QGraphicsScene; //限定新建QGraphicsScene对象的显示区域 scene->setSceneRect(-200,-200,400,400); QPixmap *pixmap = new QPixmap("image.png"); pixItem = new PixItem(pixmap); scene->addItem(pixItem); pixItem->setPos(0,0); view = new QGraphicsView; //新建一个视图对象 view->setScene(scene); //将视图对象与场景相连 view->setMinimumSize(400,400); //设置视图的最小尺寸为(400,400) ctrlFrame = new QFrame; createControlFrame(); //新建主窗体右侧的控制面板区 //主窗口布局 QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->setMargin(10); mainLayout->setSpacing(20); mainLayout->addWidget(view); mainLayout->addWidget(ctrlFrame); setLayout(mainLayout); setWindowTitle(tr("Graphics Item Transformation"));//设置主窗体的标题 } void MainWidget::createControlFrame() { //旋转控制 QSlider *rotateSlider = new QSlider; rotateSlider->setOrientation(Qt::Horizontal); rotateSlider->setRange(0,360); QHBoxLayout *rotateLayout = new QHBoxLayout; rotateLayout->addWidget(rotateSlider); QGroupBox *rotateGroup = new QGroupBox(tr("Rotate")); rotateGroup->setLayout(rotateLayout); //缩放控制 QSlider *scaleSlider = new QSlider; scaleSlider->setOrientation(Qt::Horizontal); scaleSlider->setRange(0,2*scaleValue); scaleSlider->setValue(scaleValue); QHBoxLayout *scaleLayout = new QHBoxLayout; scaleLayout->addWidget(scaleSlider); QGroupBox *scaleGroup = new QGroupBox(tr("Scale")); scaleGroup->setLayout(scaleLayout); //切变控制 QSlider *shearSlider = new QSlider; shearSlider->setOrientation(Qt::Horizontal); shearSlider->setRange(0,2*shearValue); shearSlider->setValue(shearValue); QHBoxLayout *shearLayout = new QHBoxLayout; shearLayout->addWidget(shearSlider); QGroupBox *shearGroup = new QGroupBox(tr("Shear")); shearGroup->setLayout(shearLayout); //位移控制 QSlider *translateSlider = new QSlider; translateSlider->setOrientation(Qt::Horizontal); translateSlider->setRange(0,2*translateValue); translateSlider->setValue(translateValue); QHBoxLayout *translateLayout = new QHBoxLayout; translateLayout->addWidget(translateSlider); QGroupBox *translateGroup = new QGroupBox(tr("Translate")); translateGroup->setLayout(translateLayout); connect(rotateSlider,SIGNAL(valueChanged(int)),this,SLOT(slotRotate(int))); connect(scaleSlider,SIGNAL(valueChanged(int)),this,SLOT(slotScale(int))); connect(shearSlider,SIGNAL(valueChanged(int)),this,SLOT(slotShear(int))); connect(translateSlider,SIGNAL(valueChanged(int)),this,SLOT(slotTranslate(int))); //控制面板布局 QVBoxLayout *frameLayout = new QVBoxLayout; frameLayout->setMargin(10); frameLayout->setSpacing(20); frameLayout->addWidget(rotateGroup); frameLayout->addWidget(scaleGroup); frameLayout->addWidget(shearGroup); frameLayout->addWidget(translateGroup); ctrlFrame->setLayout(frameLayout); } void MainWidget::slotRotate(int value) { view->rotate(value-angle); angle = value; } void MainWidget::slotScale(int value) { qreal s; if(value>scaleValue) s=pow(1.1,(value-scaleValue)); else s=pow(1/1.1,(scaleValue-value)); view->scale(s,s); scaleValue=value; } void MainWidget::slotShear(int value) { view->shear((value-shearValue)/10.0,0); shearValue=value; } void MainWidget::slotTranslate(int value) { view->translate(value-translateValue,value-translateValue); translateValue=value; } MainWidget::~MainWidget() { }
#ifndef PIXITEM_H #define PIXITEM_H #include <QGraphicsItem> #include <QPixmap> #include <QPainter> class PixItem : public QGraphicsItem { public: PixItem(QPixmap *pixmap); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private: QPixmap pix; //作为图元显示的图片 }; #endif // PIXITEM_H
#include "pixitem.h"
PixItem::PixItem(QPixmap *pixmap)
{
pix = *pixmap;
}
QRectF PixItem::boundingRect() const
{
return QRectF(-2-pix.width()/2,-2-pix.height()/2,pix.width()+4, pix. height()+4);
}
void PixItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
painter->drawPixmap(-pix.width()/2,-pix.height()/2,pix);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。