天天看點

我的QT Creator學習筆記(二十三)——圖形視圖

Qt提供了圖形視圖架構(Graphics View Framework)、動畫架構(The Animation Framework)和

參考文獻:《Qt Creator 快速入門》第三版 霍亞飛編著

狀态機架構(The State Machine Framework)來實作更加進階的圖形和動畫應用。

一、圖形視圖架構的結構

圖形視圖架構提供了一個居于圖形項的模型視圖程式設計方法,主要由場景、視圖和圖形項三部分組成,這三部分分别由QGraphicsScene、QGraphicsView和QGraphicsItem這3個類來表示。多視圖可以看成一個場景,場景中包含各種各樣幾何形狀的圖形項。

1.1場景QGraphicsScene

QGraphicsScene提供了圖形視圖架構中的場景,場景有以下功能:

  • 提供用于管理大量圖形的告訴接口;
  • 傳播事件到某一個圖形項
  • 管理圖形項的狀态,比如選擇和處理焦點
  • 提供五變換的渲染功能,主要用于列印

場景是圖形項QGraphicsItem對象的容器,可以調用QgraphicsScenen::addItem()函數将圖形項添加到場景中,然後調用任意一個圖形項發現函數(QgraphicsScenen::items()、QgraphicsScenen::itemAt()、QgraphicsScenen::foucusItem()等)來檢索添加的圖形項,調用QgraphicsScenen::removeItem()函數删除圖形項。

1.2視圖QGraphicsView

QGraphicsView提供了視圖部件,它用來使場景中的内容可視化。預設的QGraphicsView提供了一個QWidget作為視口部件,如果要使用OpenGL進行渲染,則可以調用QGraphicsView::setViewPort()函數設定QOpenGLWidget作為視口。可以對視圖設定前景色和背景色(也可以對整個場景設定)。

場景和視圖的示例代碼如下

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QDebug>

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    //建立場景
    QGraphicsScene scene;
    //建立矩形圖形項
    QGraphicsItem* item=new QGraphicsRectItem(0,0,100,100);
    //将圖形添加到場景中
    scene.addItem(item);
    //輸出(50,50)點處的圖形項
    qDebug()<<scene.itemAt(50,50,QTransform());

   //為場景建立視圖
    QGraphicsView view(&scene);
    //設定場景的前景色
    view.setForegroundBrush(QColor(255,255,0,100));
    //設定場景的背景圖檔
    view.setBackgroundBrush(QPixmap("../myscene/background.jpg"));
    view.resize(400,300);
    view.show();
    return app.exec();
}

           

運作效果

我的QT Creator學習筆記(二十三)——圖形視圖

1.3圖形項

QGraphicsItem是圖形項的基類,主要支援如下功能:

  • 滑鼠按下、移動、釋放、輕按兩下、懸停、滾輪和右鍵菜單。
  • 鍵盤輸入焦點和鍵盤事件。
  • 拖放事件。
  • 分組,使用QGraphicsItemGroup通過parent-child關系來實作。
  • 碰撞檢測。
  • 使用setData()和data接口進行資料存儲和擷取。

要實作自定義的圖形項,首先定義一個QGraphicsItem的子類,然後重新實作它的兩個純虛公共函數boundingRect()和paint(),前者用來傳回要繪制圖形項的矩形區域,後者用來執行實際的繪圖操作。

實列代碼如下,類頭檔案

#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsItem>

class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);
};

#endif // MYITEM_H
           

類實作

#include "myitem.h"
#include <QPainter>

MyItem::MyItem()
{

}

QRectF MyItem::boundingRect() const
{
    qreal penWidth=1;
    return QRectF(0-penWidth/2,0-penWidth/2.0,200+penWidth,200+penWidth);

}

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setBrush(Qt::red);
    painter->drawRect(0,0,200,200);
}
           

 二、圖形視圖架構的坐标系統和事件處理

2.1圖形項坐标

圖形項使用自己的本地坐标系統,坐标通常是以它們的中心為原點(0,0),而這也是所有變換的中心。圖形項預設位置是父圖形項或者場景的原點處,可以使用setPos函數指定其位置。使用setZvalue設定顯示層級,Z越大顯示層級越高。

     2.2場景坐标

場景坐标是所有圖形項的基礎坐标吸引。描述了每一個頂層圖形項的位置,也用于處理所有從視圖傳到場景上的事件。場景坐标的原點在場景的中心,x和y坐标分别向右和下增大。

2.3視圖坐标

視圖的坐标就是部件的坐标。視圖坐标的每一個機關對應一個像素,原點(0,0)在QGraphicsView視口的左上角。所有的滑鼠事件和拖放事件最初都是使用視圖坐标接收的。

2.4坐标映射

映射函數 描述
QGraphicsView::mapToScene() 從視圖坐标系統映射到場景坐标系統
QGraphicsView::mapFromScene() 從場景坐标系統映射到視圖坐标系統
QGraphicsItem::mapToScene() 從圖形項的坐标系統映射到場景的坐标系統
QGraphicsItem::mapFromScene() 從場景的坐标系統映射到圖形項的坐标系統
QGraphicsItem::mapToParent() 從本圖形項的坐标系統映射到父圖形項的坐标系統
QGraphicsItem::mapFromParent() 從父圖形項的坐标系統映射到本圖形項的坐标系統
QGraphicsItem::mapToItem() 從本圖形項的坐标系統映射到另一個圖形項的坐标系統
QGraphicsItem::mapFromItem() 從另一個圖形項的坐标系統映射到本圖形項的坐标系統

  示例代碼

myView類定義及實作

#ifndef MYVIEW_H
#define MYVIEW_H
#include <QGraphicsView>
class MyView:public QGraphicsView
{
    Q_OBJECT
public:
   explicit MyView(QWidget* parent=0);
protected:
    void mousePressEvent(QMouseEvent *event);
};

#endif // MYVIEW_H
           
#include "myview.h"
#include <QMouseEvent>
#include <QGraphicsItem>
#include <QDebug>

MyView::MyView(QWidget *parent):QGraphicsView(parent)
{

}

void MyView::mousePressEvent(QMouseEvent *event)
{
    //分别擷取單擊處在視圖、場景和圖形中的坐标,并輸出
    QPoint viewPos=event->pos();
    qDebug()<<"viewPos:"<<viewPos;
    QPointF scenePos=mapToScene(viewPos);
    qDebug()<<"scenePos:"<<scenePos;
    QGraphicsItem* item=scene()->itemAt(scenePos,QTransform());
    if(item)
    {
        QPointF itemPos = item->mapFromScene(scenePos);
        qDebug()<<"itemPos:"<<itemPos;
    }
}
           

mian函數

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QDebug>
#include "myitem.h"
#include "myview.h"

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    //建立場景
    QGraphicsScene scene;
    //建立自定義圖形項
    QGraphicsItem* item=new MyItem;
    //将圖形添加到場景中
    scene.addItem(item);
    item->setPos(10,10);
    QGraphicsItem* rectItem=scene.addRect(QRect(0,0,100,100),QPen(Qt::blue),QBrush(Qt::green));
    rectItem->setPos(20,20);
    rectItem->setParentItem(item);
    rectItem->setRotation(45);
    MyView view;
    view.setScene(&scene);
    view.setForegroundBrush(QColor(255,255,0,100));
    view.setBackgroundBrush(QPixmap("../myscene/background.jpg"));
    view.resize(400,300);
    view.show();
    return app.exec();
}

           

運作,點選圖示輸出資訊

我的QT Creator學習筆記(二十三)——圖形視圖

2.5事件處理與傳播

圖形視圖架構中的事件都是先由視圖接收,然後傳遞給場景,再由場景傳遞給相應的圖形項。對于鍵盤事件會傳遞給獲得焦點的圖形項。

繼續閱讀