Qt實現(xiàn)拖動單個控件移動的示例代碼
做慣了靜態(tài)圖,今天來搞一搞動態(tài)圖吧,首先來個最基礎(chǔ)的功能:如果讓一個控件拖動起來。
展示效果:

按照以往簡單的做法,使用mouseMoveEvent、mousePressEvent、mouseReleaseEvent也是可以實現(xiàn)的。這是最基礎(chǔ)的移動做法。
今天,不使用那種簡單的做法,采用Qt一種特有的拖動方法來實現(xiàn)!
使用QDropEvent實現(xiàn)拖拽事件。
實現(xiàn)控件拖拽的流程,如下:
1:創(chuàng)建一個控件,這里使用QLabel控件。
2:選中需要拖拽的控件
3:重寫拖拽事件。
根據(jù)上述操作流程,來實現(xiàn)一個控件的拖拽吧!
1.設(shè)置窗口拖拽屬性
在Qt中,默認(rèn)是不響應(yīng)拖拽消息的,這跟mouseMoveEvent消息默認(rèn)不響應(yīng)是一樣的,必須明確調(diào)用,告訴窗口,需要響應(yīng)此消息。
this->setAcceptDrops(true);
2.創(chuàng)建初始控件
創(chuàng)建一個初始控件,用于初始拖動使用。
QLabel *labIcon = new QLabel(this);
labIcon->setText("");
labIcon->setPixmap(QPixmap(":/QDragSingleLabel/image/boat.png"));
labIcon->move(10, 10);
labIcon->show();
labIcon->setAttribute(Qt::WA_DeleteOnClose);
偷懶起見,對QLabel控件設(shè)置了窗口關(guān)閉銷毀的功能,很是方便。
3.選中控件進行拖動
鼠標(biāo)在控件上按下,開始做拖動操作;當(dāng)鼠標(biāo)抬起時,不進行拖動操作。
3.1響應(yīng)mousePressEvent事件
需要知道鼠標(biāo)是否點擊到控件上
這里需要特殊注意的是:QLabel是一個靜態(tài)控件,正常情況下是不會響應(yīng)鼠標(biāo)選中效果的。
此時,需要響應(yīng)QWidget鼠標(biāo)按下的事件,將鼠標(biāo)點擊的點轉(zhuǎn)換成是否選中QLabel控件,側(cè)面實現(xiàn)數(shù)據(jù)點擊控件效果。
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if(!child)
{
//不是QLabel控件,不進行處理
return;
}QWidget::childAt(const QPoint& p)const;說明:返回窗口小部件自身坐標(biāo)系統(tǒng)中p點處的可見子窗口小部件。
查詢到有效QLabel指針后,創(chuàng)建一個可存儲在剪貼板中的信息,通過拖放機制進行傳輸?shù)?。這里采用:QMimeData類實現(xiàn)。
優(yōu)勢該類可以確保信息在應(yīng)用程序之間安全傳輸,并且可以在相同的應(yīng)用程序內(nèi)復(fù)制。
創(chuàng)建該類并將QLabel中的數(shù)據(jù)傳入到類中,用于做拖拽使用。
QMimeData *mimeData = new QMimeData; mimeData->setData(qsEnum, itemData);
設(shè)置數(shù)據(jù)。
qsEnum:類型:QString。
在這里可以設(shè)置任意字符串,只要保證在拖拽消息時用的一個字符串就可以。為了方便統(tǒng)一,將該字符串做了統(tǒng)一設(shè)置。
const QString qsEnum = "zhongGuoHaoGongMin";//自定義數(shù)據(jù)類型
itemData:類型:QByteArray。
對QMimeData傳入的數(shù)據(jù),這里存放了QLabel的圖片以及顯示位置。
QPixmap pixmap = *child->pixmap(); QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << pixmap << QPoint(event->pos() - child->pos());
上述內(nèi)容準(zhǔn)備就緒后,創(chuàng)建拖拽類,用于數(shù)據(jù)拖拽。
QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(event->pos() - child->pos());
將數(shù)據(jù)傳遞給拖動對象,設(shè)置將在操作期間與光標(biāo)一起顯示的像素圖,并定義一個熱點的位置,該熱點將像素圖的位置置于光標(biāo)之下。
繪制拖動的位置,這里采用了QPainter繪制機制
QPixmap tempPixmap = pixmap; QPainter painter; painter.begin(&tempPixmap); painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127)); painter.end(); child->setPixmap(tempPixmap);
開始拖動操作,調(diào)用QDrag::exec();
3.2判斷控件拖動
目前只有一個控件可以拖動,那么,當(dāng)創(chuàng)建多個拖動控件時,該如何判斷要拖動哪個呢?
這時候,在創(chuàng)建QMimeData傳入的自定義數(shù)據(jù)類型就起到作用了。
當(dāng)數(shù)據(jù)類型是qsEnum時,進行判斷,如果不是,不進行判斷。
if (event->mimeData()->hasFormat(qsEnum))
{
//進行判斷
}
else
{
event->ingnore(); //忽略判斷
}事件:dragEnterEvent、dragMoveEvent、dropEvent都需要這樣判斷。
3.3事件處理
當(dāng)前是匹配的自定義數(shù)據(jù)類型時,并且是該資源是,接受拖動進入事件,并設(shè)置當(dāng)前為拖動事件。
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}否則設(shè)置執(zhí)行操作并接收該事件
else
{
event->acceptProposedAction();
}3.4結(jié)束拖動
結(jié)束拖動,響應(yīng)事件:virtual void dropEvent(QDropEvent *event)override;
除了處理操作3中的事件處理,還需要當(dāng)鼠標(biāo)結(jié)束操作時,需要在新的位置上重新創(chuàng)建QLabel控件。并將鼠標(biāo)按下時創(chuàng)建的QMimeData數(shù)據(jù)獲取出來,顯示到新創(chuàng)建的QLabel控件上。
QByteArray itemData = event->mimeData()->data(qsEnum); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QPixmap pixmap; QPoint offset; dataStream >> pixmap >> offset; QLabel *newIcon = new QLabel(this); newIcon->setPixmap(pixmap); newIcon->move(event->pos() - offset); newIcon->show(); newIcon->setAttribute(Qt::WA_DeleteOnClose);
dropEvent消息是什么時候被觸發(fā)呢?
當(dāng)鼠標(biāo)左鍵彈起時,說明結(jié)束了控件拖動事件,需要調(diào)用dropEvent并重新創(chuàng)建控件,顯示新位置。
Qt::DropAction n = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
if (n == Qt::MoveAction)
{
//結(jié)束操作
child->close();
}
else
{
//繼續(xù)拖動控件,實時顯示新位置
child->show();
child->setPixmap(pixmap);
}到此這篇關(guān)于Qt實現(xiàn)拖動單個控件移動的示例代碼的文章就介紹到這了,更多相關(guān)Qt拖動控件移動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++函數(shù)指針和回調(diào)函數(shù)使用解析
這篇文章主要為大家詳細(xì)介紹了C++函數(shù)指針和回調(diào)函數(shù)的使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10
C++基礎(chǔ)入門教程(一):基礎(chǔ)知識大雜燴
這篇文章主要介紹了C++基礎(chǔ)入門教程(一):基礎(chǔ)知識大雜燴,本文講解了注釋、頭文件、命名空間等內(nèi)容,需要的朋友可以參考下2014-11-11
C語言strlen和sizeof在數(shù)組中的使用詳解
對于 strlen 和 sizeof,相信不少程序員會混淆其功能。雖然從表面上看它們都可以求字符串的長度,但二者卻存在著許多不同之處及本質(zhì)區(qū)別2021-10-10

