日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt学习笔记-----拖放

發(fā)布時間:2024/4/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt学习笔记-----拖放 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

拖放,拖動和釋放(Drag and Drop),允許用戶利用鼠標(biāo)在不同組件之間或一個組件上進行數(shù)據(jù)的拖動。如果哪個組件支持拖放操作,就在該組件的設(shè)計上實現(xiàn)某些必要的函數(shù)。比如說,我們可能需要在MainWindow這個主窗口上實現(xiàn)拖放,那就在這個類中實現(xiàn)一些函數(shù)。如果我們自定義了一個組件,比如說定義了一個類MyDnDWidget繼承自QWidget,我們就在MyDndWidget類中實現(xiàn)特定的函數(shù)來支持拖放。

Drag and Drop Types

QMimeData類是Qt內(nèi)部的一個容器,它記錄著大量擁有Mime Type(元類型)的數(shù)據(jù)??梢园阉?dāng)成是一個map,每一個元素都是”Mime Type, Mime Data”這樣的鍵值對,但是使用的時候不要像map一樣使用,只是用于理解。

拖放操作不只局限在文本和圖像上,任何類型的信息在拖放操作中都能被轉(zhuǎn)換。為了在應(yīng)用之間拖動信息,這些應(yīng)用彼此都應(yīng)該知道他們允許接收哪種數(shù)據(jù)格式,同時也應(yīng)該知道他們可以產(chǎn)生哪種數(shù)據(jù)格式。這個是由MIME Types實現(xiàn)的。

被構(gòu)造的QDrag對象包含MIME Types的列表,它能使用這些去表現(xiàn)數(shù)據(jù),同時接收拖動數(shù)據(jù)的那個窗體使用這些MIME Types中的一個去訪問數(shù)據(jù)。Mime Type可以是Qt中提供的,也可以是用戶自定義的,如果需要自定義一個Mime Type,可以重新實現(xiàn)mimeTypes()函數(shù):

mimeTypes

QStringList QAbstractItemModel::mimeTypes() const

這個函數(shù)返回允許的Mime Types列表。默認(rèn)情況下,內(nèi)置的models和views使用內(nèi)部的Mime Type,比如text/uri-list。
當(dāng)重新實現(xiàn)一個支持拖放操作的model時,如果設(shè)計者想要返回的數(shù)據(jù)格式不同于內(nèi)部的Mime Type,那就需要重新實現(xiàn)這個函數(shù)來返回自定義的Mime Types列表。通常的實現(xiàn)形式為:

QStringList types; types << /* the custom mime types */; return types;

如果在自定義model中重新實現(xiàn)了這個函數(shù),那么同時也需要重新實現(xiàn)mimeData()和dropMimeData()函數(shù):

mimeData

QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const

這個函數(shù)返回一個QMimeData *類型的對象,這個對象包含序列化的數(shù)據(jù)元素,而那些數(shù)據(jù)元素存儲在形參indexes中。換句話說,就是將模型索引列表indexes中的數(shù)據(jù)序列化,然后存儲在一個QMimeData中,最后返回這個QMimeData指針。序列化的方法是使用QByteArray和QDataStream兩個類。通常的實現(xiàn)格式為:

if(indexes.isEmpty())return 0;QMimeData *mimeData = new QMimeData; QByteArray encodeData;QDataStream stream(&encodeData, QIODevice::WriteOnly); foreach(QModelIndex index, indexes) {if(index.value()){/* 將index中存儲的數(shù)據(jù)取出來 */stream << /* 數(shù)據(jù)1 */ << /* 數(shù)據(jù)2 */ << /* ... */;} }mimeData->setData(/* your custom mime types */, encodeData); return mimeData;

需要注意的是,當(dāng)模型索引列表indexes為空時,返回0;

dropMimeData

bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)

當(dāng)Qt檢測到有Mime Data被釋放到以該模型為model的組件上時,相應(yīng)model的這個函數(shù)被調(diào)用。設(shè)計者需要重新實現(xiàn)這個函數(shù)來處理被釋放的數(shù)據(jù),通常是將數(shù)據(jù)存儲到(插入或追加到)model的數(shù)據(jù)結(jié)構(gòu)中。如果這個釋放動作和數(shù)據(jù)被model處理則返回true,否則返回false;
參數(shù)中的row, column, parent指明數(shù)據(jù)釋放的位置。如果row和column為-1,意味著被釋放的數(shù)據(jù)釋放到了parent上,通常是追加到parent的孩子中。如果row和column大于等于0,則被插入到parent孩子的特定位置。
通常的實現(xiàn)格式為:

if(!data->hasFormats(/* the custom mime types */)return false; if(action == Qt::IgnoreAction)return true;/* 確定插入的位置position */QByteArray encodeData = data->data(/* the custom mime types */); QDataStream stream(&encodeData, Qt::ReadOnly); while(!stream.atEnd()) {stream >> /* 數(shù)據(jù)1 */ >> /* 數(shù)據(jù)2 */ >> /* ... */;beginInsertRows(parent, position, position);/* model內(nèi)部數(shù)據(jù)結(jié)構(gòu)執(zhí)行插入操作 */endInsertRows();++position; } return true;

Drop Action

在拖放模型中,用戶既可以拖動信息的拷貝(復(fù)制)也可以拖動信息本身(剪切)到一個新地方。但是直到拖放操作完成之后程序才知道用戶是想剪切還是想拷貝。這在拖動不同組件之間的信息時沒有什么影響,但是在同一個組件上拖動時,檢查使用了哪種drop action是很重要的。

Qt::DropAction

Qt::MoveAction 移動數(shù)據(jù)本身(剪切) Qt::CopyAction 復(fù)制數(shù)據(jù)(復(fù)制) Qt::IgnoreAction 忽略數(shù)據(jù)

在釋放數(shù)據(jù)的時候,Qt會調(diào)用鼠標(biāo)所在位置上組件的dropEvent()函數(shù),設(shè)計者需要在這個函數(shù)中告訴拖放操作的數(shù)據(jù)源drop action以便數(shù)據(jù)源確定是復(fù)制還是剪切。

dropEvent

void QWidget::dropEvent(QDropEvent *event)

通知數(shù)據(jù)源drop action

event->setDropAction(Qt::MoveAction); /* 通知數(shù)據(jù)源刪除原數(shù)據(jù) */ event->accept();

或者

event->setDropAction(Qt::CopyAction); /* 通知數(shù)據(jù)源保留原數(shù)據(jù) */ event->accept();

通常拖動操作都是開始于鼠標(biāo)點擊(mousePressEvent()函數(shù)),而每個拖動操作都是一個QDrag類,所以在鼠標(biāo)點擊函數(shù)中需要定義一個QDrag類,然后執(zhí)行拖動操作,等待釋放動作的反饋??梢园堰@個函數(shù)看成數(shù)據(jù)源。

mousePressEvent

void QWidget::mousePressEvent(QMouseEvent *event) {/* ... *//* 取出點擊位置的數(shù)據(jù),進行序列化 */QDrag *drag = new QDrag(this);drag->setMimeData(mimeData);Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction);if(dropAction == Qt::CopyAction || dropAction == IgnoreAction){/* 不需要刪除原數(shù)據(jù) */}else if(dropAction == Qt::MoveAction){/* 刪除原數(shù)據(jù) */update(/* event->pos()處的范圍矩形 */)} }

其他一些需要實現(xiàn)的函數(shù)

下面這些類處理拖放和必要的mime type的編碼和解碼:
QDrag:為以Mime Data為基礎(chǔ)的拖放轉(zhuǎn)化提供支持。
QDragEnterEvent:這個類型的事件被發(fā)送到窗口如果有數(shù)據(jù)被拖進這個窗口。
QDragLeaveEvent:這個類型的事件被發(fā)送到窗口如果有數(shù)據(jù)被拖離這個窗口。
QDragMoveEvent:當(dāng)正在拖動時,這個類型的事件會一直被發(fā)出。
QDropEvent:當(dāng)拖放操作完成時,這個類型的時候被發(fā)出。

在實現(xiàn)拖放操作時就是圍繞這幾個類來實現(xiàn)特定的函數(shù)。

dragEnterEvent

void QWidget::dragEnterEvent(QDragEnterEvent *event);

protected作用域的函數(shù)。當(dāng)鼠標(biāo)拖進一個窗體的時候,該窗體的這個函數(shù)被調(diào)用,傳遞的事件作為參數(shù)。如果這個事件被忽略了(ignored),那么這個窗體不會接收任何拖動事件。換句話說這個函數(shù)就是用于提醒Qt該組件接收的數(shù)據(jù)類型,判斷是accept()還是ignore()這個事件。通常的實現(xiàn)格式為:

if(event->mimeData()->hasFormats(/* the custom mime types */)event->accept(); elseevent->ignore();

dragLeaveEvent

void QWidget::dragLeaveEvent(QDragLeaveEvent *event);

顧名思義,這個函數(shù)就是當(dāng)拖動超出該組件范圍時調(diào)用的。

dragMoveEvent

void QWidget::dragMoveEvent(QDragMoveEvent *event);

當(dāng)正在拖動時,會一直調(diào)用這個函數(shù)。可以改變一些變量比如記錄此時的投影矩形,然后在繪制函數(shù)中繪制。

paintEvent

void QWidget::paintEvent(QPaintEvent *event);

這個函數(shù)就是用于繪制所在類的。它可以被調(diào)用由以下理由:
1.repaint()或者update()函數(shù)被調(diào)用;
2.窗口部件被遮擋并且已經(jīng)被Qt發(fā)現(xiàn);
3.其他的理由

繪制的時候使用畫刷類QPainter

QPainter painter; painter.begin(this); /* 繪制代碼 */ painter.end();

總結(jié)

以上是生活随笔為你收集整理的Qt学习笔记-----拖放的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。