QT图形视图框架
文章目錄
- Graphics View框架結構的主要特點
- Graphics View框架結構的三元素
- 1、場景類:QGraphicsScene類
- 2、視圖類: QGraphicsView 類
- 3、圖元類(QGraphicsItem)
- Graphics Viewk框架結構的坐標系統
- 1.場景坐標
- 2.視圖坐標
- 3、圖元坐標
- 圖形視圖實例
Graphics View框架結構的主要特點
Graphics View框架結構的主要特點如下:
(1) 在Graphics View框架結構中,系統可以利用Qt繪圖系統的反鋸齒、OpenGL工具來改善繪圖性能。
(2) Graphics View支持事件傳播體系結構,可以使圖元場景(scene)中的交互能力提高1倍,圖元能夠處理鍵盤事件和鼠標事件。其中,鼠標事件包括鼠標被按下、移動、釋放和雙擊,還可以跟蹤鼠標的移動。
(3) 在Graphics View框架中,通過二元空間劃分樹(Binary Space Partitioning,BSP)提供快速的圖元查找,這樣就能夠實時地顯示包含上百萬個圖元的大場景。
Graphics View框架結構的三元素
Graphics View框架結構主要包含了場景類(QGraphicsScene)、視圖類(QGraphicsView)和圖元類(QGraphicsItem)。場景類提供了一個用于管理位于其中的眾多圖元容器,視圖類用于顯示場景中的圖元,一個場景可以通過多個視圖表現,一個場景包括多個幾何圖形。它們三者之間的關系可用圖表示:
1、場景類:QGraphicsScene類
它是一個用于放置圖元的容器,本身是不可見的,必須通過與之相連的視圖類來顯示及與外界進行交互操作。
場景類主要完成的工作包括提供對它包含的圖元的操作接口和傳遞事件、管理各個圖元的狀態(如選擇和焦點處理)、提供無變換的繪制功能(如打印)等。
事件傳播體系結構將場景事件發送給圖元,同時也管理圖元之間的事件傳播。如果場景接收了在某一點的鼠標單擊事件,場景會將事件傳給這一點的圖元。
| QGraphicsScene::addItem( ) | 可以添加一個圖元到場景中 |
| QGraphicsScene::items( ) | 和一些重載函數能夠返回和點、矩形、多邊形或向量路徑相交的所有圖元。 |
| QGraphicsScene::itemAt( ) | 返回指定點的最頂層圖元。 |
| QGraphicsScene::setSelectedAreas() | 選擇圖元,選擇區域可以是任意的形狀,使用QPainterpath表示。 |
| QGraphicsScene::selectedItems( ) | 得到當前選擇的圖元列表。 |
| QGraphicsScene::setFocusItem( ) 或QGraphicsScene::setFocus( ) | 設置圖元的焦點。 |
| QGraphicsScene::focusItem( ) | 函數獲得當前具有焦點的圖元。 |
| QGraphicsScene::reader( ) | 函數在繪圖設備上繪制場景。 |
2、視圖類: QGraphicsView 類
它提供一個可視的窗口,用于顯示場景中的圖元。在同一個場景中可以有多個視圖,也可以為相同的數據集提供幾種不同的視圖。視圖接收鍵盤和鼠標的輸入事件,并將它們翻譯為場景事件(將坐標轉換為場景的坐標)。
| QGraphicsView::setViewport( ) | 將視圖設置為QGLWidget。 |
| QGraphicsView::matrix( ) | 可以變換場景的坐標,實現場景縮放和旋轉。 |
| QGraphicsView::mapToScene( ) 和QGraphicsView::mapFromScene( ) | 用于場景的坐標進行轉換。 |
3、圖元類(QGraphicsItem)
它是場景中各個圖元的基類,在它的基礎上可以繼承出各種圖元類,Qt已經預置的包括直線(QGraphicsLineItem)、橢圓(QGraphicsEllipseItem)、文本圖元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。當然,也可以在QGraphicsItem類的基礎上實現自定義的圖元類,即用戶可以繼承QGraphicsItem實現符合自己需要的圖元。
QGraphicsItem主要支持如下功能:
- 鼠標按下、移動、釋放、雙擊、懸停、滾輪和右鍵菜單事件。
- 處理鍵盤輸入事件。
- 拖 處理拖曳事件。
- 碰撞檢測。
此外,圖元有自己的坐標系統,也提供場景和圖元。圖元還可以通過QGraphicsItem::matrix( )函數來進行自身的交換,可以包含子圖元。
Graphics Viewk框架結構的坐標系統
Graphics View 坐標基于笛卡兒坐標系,一個圖元的場景具有x坐標和y坐標。當使用沒有變換的視圖觀察場景時,場景中的一個單元對應屏幕上的一個像素。
三個Graphics View 基本類有各自不同的坐標系,場景坐標、視圖坐標和圖元坐標。Graphics View提供了三個坐標系統之間的轉換函數。在繪制圖形時,GraphicsView 的場景坐標對應QPainter的邏輯坐標、視圖坐標和設備坐標。
1.場景坐標
場景坐標是所有圖元的基礎坐標系統。場景坐標系統描述了項層的圖元,每個圖元都有場景坐標和相應的包容框。場景坐標的原點在場景中心,坐標原點是x軸正方向向右,y軸正方向向下。
QGraphicsScene類的坐標系以中心為原點(0,0), 如下圖所示。
2.視圖坐標
視圖坐標是窗口部件的坐標。視圖坐標的單位是像素。QGraphicsView視口的左上角是(0,0),X軸正方向向右,Y軸正方向向下。所有的鼠標事件最開始都是使用視圖坐標。
QGraphicsView類繼承自QWidget類,因此它和其他的QWidget類一樣以窗口的左上角作為自己坐標系的原點,如下圖所示。
3、圖元坐標
圖元使用自己的本地坐標,這個坐標系統通常以圖元中心為原點,這也是所有變換的原點。圖元坐標方向是X軸正方向向右,Y軸正方向向下。創建圖元后,只需要注意圖元坐標就可以了,QGraphicsScene和QGraphicsView會完成所有的變換。
QGraphicsItem類的坐標系,在調用QGraphicsItem類的paint()函數重畫圖元時則以此坐標系為基準,如下圖所示。
根據需要,Qt提供了這三個坐標系之間的互相轉換函數,以及圖元與圖元之間的轉換函數,若需從QGraphicstem坐標系中的某點坐標轉換到場景中的坐標,則可調用QGraphicstem 的mapToScene( )函數進行映射。而GraphicsItem的mapToParent()函數則可將QGraphicsItem 坐標
系中的某點坐標映射至它的上一級坐標系中,有可能是場景坐標,也有可能是另一個QGraphicsItem坐標。
Graphics View框架提供了多種變換函數,如下表所示:
| QGraphicsView::mapToScene() | 視圖到場景 |
| QGraphicsView::mapFromScene() | 場景到視圖 |
| QGraphicsItem:: mapFromScene() | 場景到圖元 |
| QGraphicsItem:: mapToScene() | 圖元到場景 |
| QGraphicsItem:: mapToParent() | 子圖元到父圖元 |
| QGraphicsItem:: mapFromParent() | 父圖元到子圖元 |
| QGraphicsItem:: mapToItem() | 本圖元到其他圖元 |
| QGraphicsItem:: mapFromItem() | 其他圖元到本圖元 |
圖形視圖實例
設計界面,一只蝴蝶在屏幕上不停地上下飛舞。
操作步驟:
(1) 新建Qt Widgets Application(這里是Qt5,Qt4選Qt GUI應用),項目名為“Buterly", 基類選擇”QMainWindow"(這個隨便吧,后面用不到),類名命名默認為“MainWindow",取消“創建界面”復選框的選中狀態。單擊“下一步”按鈕,最后單擊“完成”按鈕,完成該項目工程的建立。
(2)在“Butterfly" 項目名上單擊鼠標右鍵,在彈出的快捷菜單中選擇“添加新文件…”選
項,在彈出的對話框中選擇“C++類”選項。單擊“Choose…”按鈕,在彈出的對話框的“Base
class"下拉列表框中選擇基類名“QObject",在“類名"文本框中輸入類的名稱“Butterfly".
(3) 單擊“下一步”按鈕,單擊“完成”按鈕,添加文件“buttrfly.h" 和"butterfly.cpp”。
(4) Butterly 類繼承自QObject類、QGraphicstem 類(這個自己添加),在頭文件Butterfly.h"中完成的代碼如下:
butterfly.h文件:
#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 = 0);void timerEvent(QTimerEvent *);QRectF boundingRect() const; protected:void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private:bool up;QPixmap pix_up;QPixmap pix_down;qreal angle; //qreal是float的類型定義};#endif // BUTTERFLY_H其中,
(a) void timerEvent(QTimerEvent*):定時器實現動畫的原理是在定時器的 timerEvent() 中對QGraphicsItem進行重繪。
(b) QRectF boundingRect() const:為圖元限定區域范圍,所有繼承自QGraphicsItem的自定義圖元都必須實現此函數。
? bool up:用于標志蝴蝶翅膀的位置(位于上或下),以便實現動態效果。
butterfly.cpp文件
boundingRect( ) 函數為圖元限定區域范圍。此范圍是以圖元自身的坐標系為基礎設定的。具體實現代碼如下:
QRectF Butterfly::boundingRect() const {qreal adjust = 10;return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,\pix_up.width()+adjust*2,pix_up.height()+adjust*2);}在重畫函數paint() 中,首先判斷當前已顯示的圖片是pix_up還是pix_down。實現蝴蝶翅膀上下飛舞效果時,若當前顯示的是pix_up圖片,則重繪pix_down圖片,反之亦然。具體實現代碼如下:
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;} }定時器的timerEvent() 函數實現蝴蝶的飛舞,具體實現代碼如下:
void Butterfly::timerEvent(QTimerEvent *) {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 = (qrand()%20)-10.0;setPos(mapToParent(dx,dy)); }其中,
(a) setPos(mapToParent(dx,dy)):dx、dy完成蝴蝶隨機飛行的路徑,且dx、dy是相對于蝴蝶的坐標系而言的,因此應使用mapToParent() 函數映射為場景的坐標。
main.cpp文件
圖片:
運行效果:
總結
- 上一篇: 学习笔记(十二)——虚拟机安装和pych
- 下一篇: s3c2440移植MQTT