QT開發(四十)——GraphicsView編程

QT開發(四十)——GraphicsView編程

1、QGraphicsScene

一、QGraphicsScene

QGraphicsScene繼承自QObject,是一個管理圖元的容器,與QGraphicsView合用能夠在2D屏幕上顯示如線、三角形、文本、自定義圖元等圖元。算法

QGraphicsScene是不可見的,只用於管理圖元。爲了查看場景,須要建立一個視圖組件。編程

    一個場景分爲三個層:圖元層、前景層和背景層。場景的繪製老是從背景層開始,而後是圖形項層,最後是前景層。api

2、事件處理與傳播

    QGraphicsScene的責任之一是傳播來自視圖的事件。要發送一個事件到場景,須要構造一個繼承自QEvent的事件,使用QApplication::sendEvent()函數發送事件。event()函數負責派發事件到各個圖元。經常使用的事件會被便利事件處理函數處理,如鼠標按下事件會被mousePressEvent()函數處理。app

    按鍵事件會被派發到焦點圖元。爲了設置焦點圖元,能夠調用setFocusItem()函數,或是圖元自身調用QGraphicsItem::setFocus()函數。調用focusItem()函數能夠獲取當前的焦點圖元。爲了兼容圖形組件,場景維護着本身的焦點信息。默認場景並無焦點,而且全部的按鍵事件會別丟棄。若是setFocus()函數被調用,或是場景中一個圖元得到了焦點,場景會自動得到焦點。若是場景有焦點,hasFocus()函數會返回true,按鍵事件會被髮送到焦點圖元。若是場景失去了焦點,而圖元有焦點(如調用clearFocus()函數),場景會維護圖元的焦點信息,一旦場景從新得到焦點,會確保最後一個有焦點的圖元得到焦點。框架

    對於懸停效果,QGraphicsScene會派發懸停事件,若是某個圖元接受了懸停事件(調用QGraphicsItem::acceptHoverEvents()),當鼠標進入圖元的區域時,圖元會接收到一個GraphicsSceneHoverEnter事件。當鼠標繼續在圖元內部移動時,QGraphicsScene會發送GraphicsSceneHoverMove事件。當鼠標離開圖元的區域時,圖元會收到一個GraphicsSceneHoverLeave事件。ide

    全部鼠標事件會被傳播到當前鼠標獲取的圖元。若是一個圖元接收了鼠標事件,並收到鼠標按下,圖元就是場景的鼠標獲取圖元。這個圖元會一直被鼠標獲取,直到圖元收到一個鼠標釋放事件。調用mouseGrabberItem()函數能夠知道當前鼠標獲取的圖元。函數

場景能夠傳遞來自視圖的事件,將事件傳遞給該點最頂層的圖元。若是一個圖元要接收鍵盤事件,那麼它必須得到焦點。並且,若是在場景中重寫了事件處理函數,那麼在該函數的最後必須調用場景默認的事件處理函數,只有這樣,圖元才能接收到該事件。oop

A、拖拽事件測試

[virtual protected] void dragEnterEvent(QGraphicsSceneDragDropEvent *event)動畫

拖入事件處理函數

[virtual protected] void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)

拖離事件梳理函數

[virtual protected] void dragMoveEvent(QGraphicsSceneDragDropEvent *event)

拖動事件處理函數

[virtual protected] void dropEvent(QGraphicsSceneDragDropEvent *event)

Drop事件處理函數

在以上拖拽事件處理函數中的末尾須要調用QGraphicsScene類相應的事件處理函數。

QGraphicsScene::dragEnterEvent(event);

QGraphicsScene::dragLeaveEvent(event);

QGraphicsScene::dragMoveEvent(event);

QGraphicsScene::dropEvent(event);

B、鼠標事件

[virtual protected] void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)

鼠標移動處理函數

[virtual protected] void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)

鼠標按下處理函數

[virtual protected] void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)

鼠標釋放處理函數

在以上鼠標事件處理函數中的末尾須要調用QGraphicsScene類相應的事件處理函數。

QGraphicsScene::mouseMoveEvent(event);

QGraphicsScene::mousePressEvent(event);

QGraphicsScene::mouseReleaseEvent(event);

3、索引算法

    索引算法,是指在場景中進行圖元查找的算法。QGraphicsScene中提供了兩種選擇,在一個枚舉變量QGraphicsScene::ItemIndexMethod中定義,分別是:

    QGraphicsSecne::BspTreeIndex :應用Binary Space Partition tree,適合於大量的靜態圖元,是默認值。

    QGraphicsScene::NoIndex :不用索引,搜索場景中全部的圖元,適合於常常進行圖元的添加、移動和刪除等操做的狀況。

    使用setItemIndexMethod()函數進行索引算法的更改。

4、邊界矩形

    圖元能夠放到場景的任何位置,場景的大小默認是沒有限制的。而場景的邊界矩形僅用於場景內部進行索引的維護。由於若是沒有邊界矩形,場景就要搜索全部的圖元,而後肯定出其邊界,這是十分費時的。因此若是要操做一個較大的場景,應該給出它的邊界矩形。

    設置邊界矩形,可使用setSceneRect()函數。

5、圖元的查找

    場景最大的優點之一就是能夠快速的鎖定圖元的位置,即便有上百萬個圖元,items()函數也能在數毫秒的時間內鎖定一個圖元的位置。items()函數有幾個重載函數來方便的進行圖元的查找。若是在場景的一個點可能重疊着幾個圖元,可使用itemAt()函數返回最上面的一個圖元。

2、QGraphicsItem

1、自定義QGraphicsItem

    QGraphicsItem是圖元的基類。

    自定義圖元,首先應該繼承QGraphicsItem,而後重寫他的兩個純虛公共函數boundingRect()和paint(),boundingRect()函數返回繪製圖元大概的區域,paint()函數用來繪製圖元內容。

    boundingRect()函數有不少用處,場景在boundingRect()來創建它的圖元的index,視圖使用boundingRect來剪切可見的圖元,在從新繪製圖元時候,來決定相互重疊的部分,此外,圖元的碰撞檢測機制也使用的boundingRect()來提供一個高效的定點,在collidesWithItem()更好的碰撞算法創建在調用函數shape(),shape()函數以QpainterPath類型返回圖元的精準的輪廓。
    場景不但願圖元的boundingRect()和shape()變化,除非該圖元被通告,若是想經過一些方法改變圖元的形狀,首先應該調用QgraphicsScene()來容許場景QgraphicsScene來刷新它的圖元記錄。

    圖元沒有得到焦點時,事件只能從視圖傳遞到場景,不能傳遞到圖元。清除圖元的焦點函數爲clearFocus()。

2、繪製

    paint()函數被QgrapicsView類調用來繪製圖元的內容,圖元默認是沒有背景或者填充顏色的。在函數中沒有被繪製的全部區域都將會發亮,能夠調用update()來重繪圖元,能夠選擇傳遞須要重繪的矩形區域(不是必須的)。取決於圖元在視圖中是否可見,圖元可能會也可能不會重繪,QgraphicsItem裏面沒有和 Qwidget::repaint()函數等價的圖元經過視圖來繪製,從父類圖元開始,而後是圖元自身,以上升的棧的順序,能夠經過調用setZValue()設置圖元的棧順序,經過zValue()來測試,具備低z-values的圖元比具備高z-value 的圖元先繪製,棧順序應用於兄弟圖元,父類圖元老是比子類圖元更早繪製。

3、排序

    全部的圖元都按照一個已經聲明的穩定的順序來繪製,聲明的順序決定了當在場景中點擊鼠標時候,哪一個圖元最早接受鼠標的輸入。一般狀況下,不須要擔憂圖元排序的問題,由於全部的圖元都按照一個在場景中聲明的天然的順序。
    在一個棧中,子類圖元在父類圖元的上面,兄弟圖元按照插入場景的順序來入棧,若是你先添加圖元A ,而後是圖元B,而後是圖元C ,棧中的順序從下往上就是ABC。能夠調用setZvalue()來設置一個圖元的相對於另外一個圖元向上、向下或者兄弟棧順序。默認的Z值是0,具備一樣的Z值的圖元會按照插入的順序來入棧。能夠調用stackBefore()來備份子類圖元的列表,直接更正圖元的順序。
    若是想讓子類圖元在父類圖元的後面,也就是先繪製子類圖元,而後再繪製父類圖元。能夠利用函數setFlag()設置ItemStacksBehindParent屬性給圖元。

4、事件處理

    QgraphicsItem從場景中經過sceneEvent()函數來接受事件,sceneEvent()函數經過一些方便的操做分散大部分事件

    ContextMenuEvent()函數接受上下文菜單事件

    FocusInEvent()和focusOutEvent()函數接受焦點進出事件 
    hoverEnterEvent()hoverMoveEvent()hoverLeaveEvent() 接受鼠標懸浮移動和離開事件
    inputMethodEvent()函數處理輸入法事件,
    keyPressEvent()keyReleaseEvent()事件處理鍵盤按下和釋放事件
    mousePressEvent()mouseMoveEvent()mouseReleaseEvent()    mouseDoubleClickEvent()處理鼠標按下、移動、釋放、雙擊事件
    經過安裝過濾器,能夠爲圖元過濾一些事件,與QT通常的事件過濾器不同,通常的過濾器只工做在Qobject及其子類。經過調用 installSceneEventFilter()爲圖元安裝事件過濾器後,被過濾的事件將會被虛函數sceneEventFilter()捕捉 到,能夠經過調用函數removeSceneEventFilter()來去除掉事件過濾器

A、拖拽事件

    GraphicsView框架爲視圖、場景、圖元提供拖拽支持。當視圖接收到拖拽事件,GraphicsView框架會將拖拽事件翻譯爲QGraphicsSceneDragDropEvent事件,再發送到場景,場景接管事件,把事件發送到光標下接受拖拽的第一個圖元。
    從圖元開始拖拽時,建立一個QDrag對象,傳遞開始拖拽的QWidget的指針。圖元能夠同時被多個視圖觀察,但只有一個視圖能夠開始拖拽。拖拽在多數狀況下是從按下鼠標或是移動鼠標開始的,在mousePressEvent()或mouseMoveEvent()中,能夠從事件中獲得原始的QWidget指針

    要在場景中取拖拽事件,須要從新實現QGraphicsScene::dragEnterEvent()QGraphicsItem子類裏任何與特定場景須要的事件處理器。圖元也能夠經過調用QGraphicsItem::setAcceptDrops()得到拖拽支持,爲了處理將要進行的拖拽,須要從新實現QGraphicsItemdragEnterEvent()dragMoveEvent()

dropEvent()dragLeaveEvent() 。

[virtual protected] void dragEnterEvent(QGraphicsSceneDragDropEvent *event)

[virtual protected] void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)

[virtual protected] void dragMoveEvent(QGraphicsSceneDragDropEvent *event)

[virtual protected] void dropEvent(QGraphicsSceneDragDropEvent *event)

B、鼠標事件

    要在自定義圖元類中處理鼠標事件,須要重寫QGraphicsItem類中鼠標按下、鼠標移動、鼠標釋放的事件。

[virtual protected] void mouseMoveEvent(QGraphicsSceneMouseEvent *event)

[virtual protected] void mousePressEvent(QGraphicsSceneMouseEvent *event)

[virtual protected] void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)

5、動畫效果

    實現圖元的動畫效果,也能夠在不一樣的層面進行。若是隻想控制一兩個圖元的動畫,通常在場景或視圖中實現。可是要是想讓一個圖元類的多個對象都進行一樣的動畫,那麼咱們就能夠在圖元類的構造函數中進行實現。

    //圖元可得到焦點

    setFlag(QGraphicsItem::ItemIsFocusable);

    //圖元可移動

    setFlag(QGraphicsItem::ItemIsMovable);

    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;

    //將圖元加入動畫對象中

    anim->setItem(this);

    //建立長爲1秒的時間線

    QTimeLine *timeLine = new QTimeLine(1000);

    //動畫循環次數爲0,表示無限循環

    timeLine->setLoopCount(0);

    //將時間線加入動畫類對象中

    anim->setTimeLine(timeLine);

    //在動畫時間的一半時圖形項旋轉180

    anim->setRotationAt(0.5,180);

    //在動畫執行完時圖形項旋轉360

    anim->setRotationAt(1,360);

    //開始動畫

    timeLine->start();

6、移動

    圖元的移動,有多種方法實現,能夠在視圖或場景上控制,但對於不一樣類型的大量圖元,怎樣能一塊兒控制呢?在圖形視圖框架中提供了advance()槽函數,advance()函數在QGraphicsSceneQGraphicsItem中都有定義,在圖元類中的原型是advance(int phase)。實現流程是,利用QGraphicsScene類的對象調用QGraphicsSceneadvance()函數,會執行兩次場景中全部圖元的advance(int phase)函數,第一次phase0,告訴全部圖形項即將要移動;第二次phase的值爲1,執行移動。

    QTimer timer;

    QObject::connect(&timer, SIGNAL(timeout()),scene, SLOT(advance()));

    timer.start(1000);

    至於圖元如何移動,須要重寫圖元類的advance()函數。

    若是在自定義圖元類的構造函數中設置爲可移動,則圖元能夠直接使用鼠標拖拽。

setFlag(QGraphicsItem::ItemIsMovable);

7、圖元的座標轉換

    QgraphicsItem支持座標轉換,對於簡單的轉換,能夠調用函數setRotation()或者setScale(),能夠傳遞一個轉換矩陣給函數setTransform(),對於一些更復雜的轉換,能夠經過調用函數setTransformations()來設置一系列組合的轉換。
    圖元轉換從父類到子類進行彙集,所以若是一個父類圖元和子類圖元都旋轉90度,那麼子類圖元就旋轉了180度;若是父類圖元和子類圖元都放大了2X倍,那麼子類圖元就被放大4X倍,圖元的轉換不影響圖元的外觀,全部和外觀有關的函數(例如contains(),update()和全部的映射mapping函數)將會在本地座標中操做,QgraphicsItem提供函數sceneTransform(),將會返回圖元全部的轉換矩陣,scenePos()將會返回圖元在場景座標中的位置,從新設置圖元的矩陣,調用函數resetTransform()
    通常的轉換回產生一個不一樣的結果,取決於轉換應用的順序,轉換順序不一樣獲得結果將不一樣。

8、主要成員函數

QVariant itemChange(GraphicsItemChange change, const QVariant & value)

    itemChange函數被QGraphicsItem調用用來標識圖元的狀態改變了,經過重載itemChange函數,能夠對本身定義事件響應。參數change是改變的圖元的改變狀態參數,value是一個新的數據,類型取決於change,change是QGraphicsItem::GraphicsItemChange枚舉變量

    在itemChange函數內部調用函數時候要謹慎,不能在itemChange函數裏面調用setPos(),參數change是ItemPositionChange時,setPos()函數將會再次調用itemChange(ItemPositionChange),造成死循環。

    void setFlag(GraphicsItemFlag flag, bool enabled = true)
 
     void setFlags(GraphicsItemFlags flags)
 
    flags設置爲圖元的屬性,若是圖元得到了光標,但flags沒有使能ItemsFocusable,圖元將會丟失光標,當圖元被選擇,但沒有使能ItemsSelectable,圖元會自動的失去選擇。
     
QPainterPath shape () const 

    以QPainterPath返回圖元在本地座標中的形狀,形狀能夠用來作不少事情,包括碰撞偵測,打擊測試,還有用來 QGraphicsScene::items() 函數
    默認的函數調用boundingRect()返回一個簡單的矩形形狀,子類能夠重載boundingRect函數,爲非矩形的圖元返回一個更加精準的形狀,例如一個圓形的圖元能夠選擇返回一個橢圓形,用來得到更好的碰撞偵測效果。

3、QGraphicsView

一、QGraphicsView簡介

    QGraphicsView繼承自QAbstractScrollArea,繼承了QWidget的特性。

    QGraphicsView提供了視圖窗口部件,使場景的內容可視化。能夠給一個場景關聯多個視圖,從而給一個數據集提供多個視口。視圖部件是一個滾動區域,能夠提供一個滾動條來顯示大型的場景。

二、事件處理

    在圖形視圖框架中,鼠標鍵盤等事件是從視圖進入的,視圖將事件傳遞給場景,場景再將事件傳遞給該點的圖元,若是該點有多個圖元,那麼就傳給最上面的圖元。爲了使事件能進一步傳播到場景,須要在從新實現事件處理函數時,在其最後將event參數傳給默認的事件處理函數。好比重寫了視圖的鼠標按下事件處理函數,那麼就在該函數的最後寫上QGraphicsView::mousePressEvent(event);

A、拖拽事件

    在QGraphicView中提供了三種拖拽模式,分別是:

    QGraphicsView::NoDrag :忽略鼠標事件,不能夠拖動。

    QGraphicsView::ScrollHandDrag :光標變爲手型,能夠拖動場景進行移動。

    QGraphicsView::RubberBandDrag :使用橡皮筋效果,進行區域選擇,能夠選中一個區域內的全部圖元。

    能夠利用setDragMode()函數進行相應設置。

[virtual protected] void dragEnterEvent(QDragEnterEvent *event)

[virtual protected] void dragLeaveEvent(QDragLeaveEvent *event)

[virtual protected] void dragMoveEvent(QDragMoveEvent *event)

[virtual protected] void dropEvent(QDropEvent *event)

在以上拖拽事件處理函數中的末尾須要調用QGraphicsView類相應的事件處理函數。

QGraphicsView::dragEnterEvent(event);

QGraphicsView::dragLeaveEvent(event);

QGraphicsView::dragMoveEvent(event);

QGraphicsView::dropEvent(event);

B、鼠標事件

[virtual protected] void mouseMoveEvent(QMouseEvent *event)

[virtual protected] void mousePressEvent(QMouseEvent *event)

[virtual protected] void mouseReleaseEvent(QMouseEvent *event)

void setMouseTracking(bool enable)

在以上鼠標事件處理函數中的末尾須要調用QGraphicsView類相應的事件處理函數。

QGraphicsView::mouseMoveEvent(event);

QGraphicsView::mousePressEvent(event);

QGraphicsView::mouseReleaseEvent(event);

4、程序實例

一、自定義視圖

CustomView.h文件:

#ifndef CUSTOMVIEW_H
#define CUSTOMVIEW_H
 
#include <QGraphicsView>
 
class CustomView : public QGraphicsView
{
    Q_OBJECT
public:
    CustomView(QWidget *parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
    void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
    void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE;
    void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE;
    void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
};
 
#endif // CUSTOMVIEW_H

CustomView.cpp文件:

#include "CustomView.h"
#include <QDebug>
 
CustomView::CustomView(QWidget *parent):QGraphicsView(parent)
{
}
 
void CustomView::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "CustomView::mousePressEvent";
    QGraphicsView::mousePressEvent(event);
}
 
void CustomView::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "CustomView::mouseMoveEvent";
    QGraphicsView::mouseMoveEvent(event);
}
 
void CustomView::mouseReleaseEvent(QMouseEvent *event)
{
    qDebug() << "CustomView::mouseReleaseEvent";
    QGraphicsView::mouseReleaseEvent(event);
}
 
void CustomView::paintEvent(QPaintEvent *event)
{
    qDebug() << "CustomView::paintEvent";
    QGraphicsView::paintEvent(event);
}
 
void CustomView::dragEnterEvent(QDragEnterEvent *event)
{
    qDebug() << "CustomView::dragEnterEvent";
    QGraphicsView::dragEnterEvent(event);
}
 
void CustomView::dragLeaveEvent(QDragLeaveEvent *event)
{
    qDebug() << "CustomView::dragLeaveEvent";
    QGraphicsView::dragLeaveEvent(event);
}
 
void CustomView::dragMoveEvent(QDragMoveEvent *event)
{
    setCursor(Qt::CrossCursor);
    qDebug() << "CustomView::dragMoveEvent";
    QGraphicsView::dragMoveEvent(event);
}
 
void CustomView::dropEvent(QDropEvent *event)
{
    qDebug() << "CustomView::dropEvent";
    QGraphicsView::dropEvent(event);
}

 

2、自定義場景

CustomScene.h文件:

#ifndef CUSTOMSCENE_H
#define CUSTOMSCENE_H
 
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPaintEvent>
 
class CustomScene : public QGraphicsScene
{
    Q_OBJECT
public:
    CustomScene(QObject *parent = 0);
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    void dragEnterEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dropEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
};
 
#endif // CUSTOMSCENE_H

CustomScene.cpp文件:

#include "CustomScene.h"
#include <QDebug>
 
CustomScene::CustomScene(QObject *parent):QGraphicsScene(parent)
{
}
 
void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "CustomScene::mousePressEvent";
    QGraphicsScene::mousePressEvent(event);
}
 
void CustomScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "CustomScene::mouseReleaseEvent";
    QGraphicsScene::mouseReleaseEvent(event);
}
 
void CustomScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "CustomScene::mouseMoveEvent";
    QGraphicsScene::mouseMoveEvent(event);
}
 
void CustomScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    qDebug() << "CustomScene::dragEnterEvent";
    QGraphicsScene::dragEnterEvent(event);
}
 
void CustomScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
    qDebug() << "CustomScene::dragLeaveEvent";
    QGraphicsScene::dragLeaveEvent(event);
}
 
void CustomScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    qDebug() << "CustomScene::dragMoveEvent";
    QGraphicsScene::dragMoveEvent(event);
}
 
void CustomScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    qDebug() << "CustomScene::dropEvent";
    QGraphicsScene::dropEvent(event);
}

3、自定義圖元

CustomItem.h文件:

#ifndef CUSTOMITEM_H
#define CUSTOMITEM_H
 
#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
 
class CustomItem : public QGraphicsItem
{
public:
    CustomItem();
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) Q_DECL_OVERRIDE;
    QRectF boundingRect() const Q_DECL_OVERRIDE;
protected:
    //鼠標事件
    void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE;
    //拖拽事件
    void dragEnterEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
    void dropEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
private:
    QColor color;
};
 
#endif // CUSTOMITEM_H

 

CustomItem.cpp文件:

#include "CustomItem.h"
#include <QDebug>
#include <QPainter>
#include <QCursor>
#include <QPen>
 
CustomItem::CustomItem()
{
    color = Qt::red;
    setFlag(QGraphicsItem::ItemIsFocusable);
    //設置圖元爲可移動的
    setFlag(QGraphicsItem::ItemIsMovable);
    setAcceptDrops(true);
}
 
void CustomItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    qDebug() << "CustomItem::paint";
    if(hasFocus()) {
        painter->setPen(QPen(QColor(255,255,255,200)));
    } else {
        painter->setPen(QPen(QColor(100,100,100,100)));
    }
    painter->setBrush(color);
    painter->drawRect(-10, -10, 20, 20);
}
 
QRectF CustomItem::boundingRect() const
{
    qreal adjust = 0.5;
    return QRectF(-10 - adjust, -10 - adjust, 20 + adjust, 20 + adjust);
}
 
void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event);
    qDebug() << "CustomItem::mousePressEvent";
    setCursor(Qt::OpenHandCursor);
}
 
void CustomItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    setCursor(Qt::DragMoveCursor);
    qDebug() << "CustomItem::mouseMoveEvent";
}
 
void CustomItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "CustomItem::mouseReleaseEvent";
    setCursor(Qt::ArrowCursor);
}
 
void CustomItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    setCursor(Qt::CrossCursor);
    qDebug() << "CustomItem::dragEnterEvent";
}
 
void CustomItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
    setCursor(Qt::ForbiddenCursor);
    qDebug() << "CustomItem::dragLeaveEvent";
}
 
void CustomItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    setCursor(Qt::CrossCursor);
    qDebug() << "CustomItem::dragMoveEvent";
}
 
void CustomItem::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    setCursor(Qt::WaitCursor);
    qDebug() << "CustomItem::dropEvent";
}

 

4、程序使用

#include "CustomScene.h"
#include "CustomView.h"
#include "CustomItem.h"
#include <QApplication>
#include <QTime>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
 
    CustomScene scene;
    scene.setSceneRect(-200, -150, 400, 300);
    for(int i = 0; i < 5; ++i) {
        CustomItem *item = new CustomItem;
        item->setPos(i * 50 - 90, -50);
        scene.addItem(item);
    }
    CustomView view;
    view.setScene(&scene);
    view.show();
 
    return a.exec();
}
相關文章
相關標籤/搜索