Qt快速入門學習筆記(畫圖篇)


1、Qt中提供了強大的2D繪圖系統,可以使用相同的API在屏幕和繪圖設備上進行繪制,它主要基於QPainter、QPaintDevice和QPaintEngine這三個類。其中QPainter用來執行繪圖操作;QPaintDevice提供繪圖設備,它是一個二維空間的抽象,可以使用QPainter在其上進行繪制;QPaintEngine提供了一些接口,可以用於QPainter在不同的設備上進行繪制。 QPainter一般在一個部件的重繪事件(Paint Event)的處理函數paintEvent()中進行繪制,首先要創建QPainter對象,然后進行圖形的繪制,最后銷毀QPainter對象。

2、在Qt窗口里面,(0, 0)點就是窗口的左上角,但這里是不包含外邊框的。而在MainWindow主窗口里面繪制時,左上角並不是指中心區域的左上角,而是包含了工具欄。

3、drawArc()畫弧線時,角度被分成了十六分之一,就是說,要想為30度,就得是30*16。

4、如果要繪制一個復雜的圖形,尤其是要重復繪制這樣的圖形,那么可以使用QPainterPath類,然后使用QPainter::drawPath()來進行繪制。QPainterPath類為繪制操作提供了一個容器,可以用來創建圖形並且重復使用。一個繪圖路徑就是由多個矩形、橢圓、線條或者曲線等組成的對象,一個路徑可以是封閉的,例如矩形和橢圓;也可以是非封閉的,例如線條和曲線。如果只是簡單的將幾個圖形拼接在一起,其實完全沒有必要用路徑,之所以要引入路徑,就是因為它的一個非常有用的功能:復制圖形路徑。創建路徑后,默認是從(0, 0)點開始繪制的。

5、Qt中每一個窗口都有一個坐標系統,默認的,窗口左上角為坐標原點,水平向右依次增大,水平向左依次減小,垂直向下依次增大,垂直向上依次減小。原點即為(0,0)點,以像素為單位增減,也可以稱為窗口坐標系

6、默認的,QPainter在相關設備的坐標系統上進行繪制,在進行繪圖時,可以使用QPainter::scale()函數縮放坐標系統;使用QPainter::rotate()函數順時針旋轉坐標系統;使用QPainter::translate()函數平移坐標系統;還可以使用QPainter::shear()圍繞原點來扭曲坐標系統。這里要分清窗口坐標系和繪圖坐標系,起始時窗口坐標系與繪圖坐標系是重合的,當進行縮放、旋轉、平移及扭曲時變化的僅僅是繪圖坐標系,而窗口坐標系始終保持不變

7、QPainter除了可以在QWidget等窗口部件上進行繪制以外,還可以在QPixmap、QImage等上面進行繪制,這些均稱為繪圖設備。為了表述方面,將QPixmap對象稱為畫布。畫布也有自己的坐標系統,畫布坐標系原點在畫布的左上角,當進行縮放、旋轉、平移及扭曲時變化的也僅僅是相對於畫布的繪圖坐標系

8、QWidget和QPixmap各有一套坐標系統,它們互不影響。無論畫布在窗口的什么位置,它的坐標原點依然在左上角,為(0,0)點,沒有變。而在畫布上我們所得到的鼠標指針的坐標值是窗口坐標系統的,不是相對於畫布坐標系的

9、整個圖形視圖結構主要包含三部分:場景(Scene)、視圖(View)和圖形項(Item),它們分別對應 QGraphicsScene 、QGraphicsView 、QGraphicsItem三個類。場景是管理圖形項的,所有的圖形項必須添加到一個場景中,但是場景本身無法可視化,我們要想看到場景上的內容,必須使用視圖。

10、QGraphicsItem類是所有圖形項的基類。圖形視圖框架對一些典型的形狀提供了一些標准的圖形項。比如上面我們使用的矩形(QGraphicsRectItem)、橢圓(QGraphicsEllipseItem)、文本(QGraphicsTextItem)等多個圖形項。但只有繼承QGraphicsItem 類實現我們自定義的圖形項時,才能顯示出這個類的強大。

11、在項目中添加新的C++類,類名設為 MyItem,基類設為QGraphicsItem。繼承QGraphicsItem類實現自定義的圖形項,必須先實現兩個純虛函數boundingRect()和paint(),前者用於定義Item的繪制范圍,后者用於繪制圖形項。

12、一個場景分為三個層:圖形項層(ItemLayer)、前景層(ForegroundLayer)和背景層(BackgroundLayer)。場景的繪制總是從背景層開始,然后是圖形項層,最后是前景層。對於前景層,我們一般不進行設置,或者像上面這樣設置為半透明的白色。

13、QGraphicsView 提供了視圖窗口部件,它使場景的內容可視化。你可以給一個場景關聯多個視圖,從而給一個數據集提供多個視口。視圖部件是一個滾動區域,就是說,它可以提供一個滾動條來顯示大型的場景。如果要使用OpenGL,你可以使用QGraphicsView::setViewport()函數來添加QGLWidget 。

14、在圖形視圖框架中,鼠標鍵盤等事件是從視圖進入的,視圖將它們傳遞給場景,場景再將事件傳遞給該點的圖形項,如果該點有多個圖形項,那么就傳給最上面的圖形項。所以要想使這個事件能一直傳播下去,我們就需要在重新實現事件處理函數時,在其最后將event參數傳給默認的事件處理函數。比如我們重寫了場景的鍵盤按下事件處理函數,那么我們就在該函數的最后寫上QGraphicsScene::keyPressEvent(event);一行代碼。

15、QGraphicsView默認使用一個QWidget作為視口部件,如果我們要使用OpenGL進行渲染,可以使用setViewport()函數來添加一個QGLWidget對象。看下面的例子。 

我們先在項目文件graphicsView04.pro中加入
QT += opengl
說明要使用OpenGL模塊,然后在myview.cpp文件中添加頭文件:
#include <QtOpenGL>
最后在構造函數中加入代碼:
QGLWidget *widget =new QGLWidget(this);
setViewport(widget);
這樣便使用OpenGL進行渲染了。關於OpenGL,我們在后面的3D繪圖部分再講。
16、itemAt()函數可以輸出場景上任意點的圖形項。而items()函數可以輸出場景上所有的圖形項。這里應該說明,items()函數返回的圖形項列表是按棧的降序排序的,也就是說,items().at(0)返回的是最后加入場景的圖形項。
       圖形項組其實也是一個圖形項,它有圖形項所擁有的所有特性。其作用就是將加入它的所有圖形項作為一個整體,對這個圖形項組進行操作,就相當於對齊中所有圖形項進行操作。圖形項組是加入它的所有圖形項的父圖形項。 我們要從圖形項組中移除一個圖形項,可以使用removeFromGroup()函數,它可以將給定的item從group中刪除,要注意這時item依然存在,它會回到group的父圖形項中,如果group沒有父圖形項,那么item就會回到場景中。我們可以使用場景的removeItme()函數來刪除group,這樣也會將group中所有的圖形項從場景中刪除。還有一種辦法是利用場景的destroyItemGroup()函數,它會刪除group並銷毀它,但是group中的所有圖形項會回到group的父圖形項中,如果它沒有父圖形項,那么所有圖形項就會回到場景中。
17、圖形視圖框架提供了兩個打印函數render(),一個是在QGraphicsScene中,一個是在QGraphicsView中,並且它們的函數原型是一模一樣的。不過它們實現的效果稍有不同。視圖的打印函數是依據視圖的坐標系進行打印的,它可以看做是程序窗口的截屏。而場景的打印函數,是依據場景的坐標系的,無論視圖怎么轉換,只要場景坐標系沒有變換,它打印出來的圖片都是一樣的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM