QTGraphics-View拖拽以及鼠標指針操做

由於QGraphicsView繼承自QWidget,它也提供了像QWidget那樣的拖拽功能。html

另外,爲了方便,Graphics View框架也爲場景以及每一個item提供拖拽支持。當視圖接收到拖拽事件,它可轉化爲QGraphicsSceneDragDropEvent,再發送到場景。場景接管這個事件,把它發送到光標下接受拖拽的第一個item。 從一個item開始拖拽時,建立一個QDrag對象,傳遞開始拖拽的那個widget的指針。Items能夠同時被多個視圖觀察,但只有一個視圖能夠開始拖拽。框架

拖拽在多數狀況下是從按下鼠標或是移動鼠標開始的,所以,在 mousePressEvent()或mouseMoveEvent()中,你能夠從事件中獲得那個原始的widget指針,例如:dom

 C++ Code 
1
2
3
4
5
6
7
8
 
void  CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QMimeData *data = 
new  QMimeData;
    data->setColor(Qt::green);
    QDrag *drag = 
new  QDrag(event->widget());
    drag->setMimeData(data);
    drag->start();
}

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

像QWidget同樣,QGraphicsItem也支持光標(QgraphicsItem::setCursor)與工具提示(QGraphicsItem::setToolTip())。當光標進入到item的區域,光標與工具提示被QGraphicsView激活(經過調用QGraphicsItem::contains()檢測)。你也能夠直接在視圖上設置一個缺省光標(QGraphicsView::setCursor)。函數

Qt自帶例程Drag and Drop Robot介紹了這兩方面的內容。工具

 

在這個demo中,能夠把機器人四周的顏色拖動到機器人的各個部位,好比說頭,臂,身軀等,而後這個部位就會變成相應的顏色,相似於換裝小遊戲。學習

下圖是通過個人一番操做後的機器人模樣:動畫

如下是我學習這個Demo的一些知識總結,僅供交流學習,若有錯誤,歡迎指正,一塊兒進步:this

圓形顏色圖元ColorItemspa

隨機顏色值:QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256));

Tooltips:setToolTip(QString("QColor(%1, %2, %3)\n%4").arg(color.red()).arg(color.green()).arg(color.blue()).arg("Click and drag this color onto the robot!"));

 鼠標移入圖元手勢 (展開的小手):setCursor(Qt::OpenHandCursor);

  • 繪製(兩個組合圓):

painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-12,-12, 30, 30);
painter->setPen(QPen(Qt::black, 1));
painter->setBrush(QBrush(color));
painter->drawEllipse(-15,-15, 30, 30);

鼠標左鍵按下:setCursor(Qt::ClosedHandCursor);

鼠標左鍵釋放:setCursor(Qt::OpenHandCursor);

鼠標左鍵移動過程(主要邏輯):

// 須要有一個最小移動距離限制(10px)
if(QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
  .length()< QApplication::startDragDistance()) {
  return;
}

 

// 建立拖動對象,並綁定一個MIME數據
QDrag*drag= new QDrag(event->widget());
QMimeData*mime= new QMimeData;
drag->setMimeData(mime);

 

PS:QMimeData is used to describe information that can be stored in the clipboard, and transferred via the drag and drop mechanism.

        QMimeData objects are usually created using new and supplied to QDrag or QClipboard objects.

 

對於從剛初始化後兩次以上的拖動,可能會出現人臉的圖像,其他狀況則是對原始圓形圖元的拖動。

設置MIME圖像數據:        QMimeData::setImageData

設置MIME純文本數據:    QMimeData::setText

設置MIME顏色數據:        QMimeData::setColorData

設置拖動熱點:                  QDrag::setHotSpot

設置拖動過程當中的圖像:    QDrag::setPixmap

執行拖動:                         QDrag::exec();

 

既然有了拖動(Drag),就得有接收拖動的地方,即釋放拖動的地方(Drop)。在本Demo中,執行Drop操做的主體是中間的搖擺機器人Robot。

首先須要使能Drop:setAcceptDrops(true);

具體須要重載如下三個關於Drag-Drop的虛函數:

void dragEnterEvent(QGraphicsSceneDragDropEvent*event) override;

void dragLeaveEvent(QGraphicsSceneDragDropEvent*event) override;

void dropEvent(QGraphicsSceneDragDropEvent*event) override;

其中QGraphicsSceneDragDropEvent類攜帶了拖動的mime數據信息,經過bool類型成員變量dragOver標識拖動是否移動到機器人身體上,移入則響應dragEnterEvent(顏色加亮顯示),移出則響應dragLeaveEvent,並置位dragOver

釋放操做則響應dropEvent將傳遞過來的顏色值賦給當前QPainter畫刷顏色,調用update來調用paint函數從新繪製。

若是頭像移入頭部則繪製頭像圖片。

全部機器人的各部件(頭、胳膊、軀幹)經過Robot類總體組織起來,並加上了動畫。

Rebort不進行任何paint操做setFlag(ItemHasNoContents);

PS:The item does not paint anything (i.e., calling paint() on the item has no effect). You should set this flag on items that do not need to be painted to ensure that Graphics View avoids unnecessary painting preparations.

Robot各部位Item的排序

 

其中,軀幹是Root Item(全部其餘Item是children或軀幹的後代),所以首先繪製(1)。 接下來,繪製頭部(2),由於它是軀幹children列表中的第一個項目。 而後繪製左上臂(3), 因爲下臂是上臂的孩子,所以下臂被拉動(4),接着是上臂的下一個兄弟,即右上臂(5),依此類推。

頭部動畫(旋轉和縮放屬性):

QPropertyAnimation*headAnimation= new QPropertyAnimation(headItem, "rotation");

QPropertyAnimation*headScaleAnimation= new QPropertyAnimation(headItem, "scale");

其他部位的動畫相似…

全部的QPropertyAnimation經過QParallelAnimationGroup組合在一塊兒並行運行。

QParallelAnimationGroup*animation= new QParallelAnimationGroup(this);

animation->addAnimation(headAnimation);

animation->addAnimation(headScaleAnimation);

最後,讓咱們繼續搖擺:

相關文章
相關標籤/搜索