網(wǎng)站建設(shè)做哪 個會計(jì)科目搜索風(fēng)云排行榜
文章目錄
- 1. 在便捷類中啟用拖放
- 2. 在模型/視圖類中啟用拖放
模型/視圖框架支持Qt的拖放應(yīng)用。
列表、表格和樹中的項(xiàng)目可以在視圖中被拖拽,數(shù)據(jù)作為MIME編碼的數(shù)據(jù)被導(dǎo)入和導(dǎo)出。標(biāo)準(zhǔn)視圖可以自動支持內(nèi)部的拖放。
默認(rèn)視圖的拖放功能并沒有被啟用,如果要進(jìn)行項(xiàng)目的拖動,就需要進(jìn)行一些屬性的設(shè)置。
如果在一個新的模型中啟用拖放功能,還需要重新實(shí)現(xiàn)一些函數(shù)。
1. 在便捷類中啟用拖放
三個便捷類QListWidget、QTreeWidget、QTableWidget中每一種類型的項(xiàng)目都默認(rèn)配置了一組不同的標(biāo)志。
每一個QListWidgetItem和QTreeWidgetItem被初始化為可用的、可檢查的、可選擇的,也可以用作拖放的源。每一個QTableWidgetItem可以被編輯和用作拖放操作的目標(biāo)。
一般還需要在視圖中設(shè)置一些屬性來使它啟用對拖放操作的內(nèi)建支持:
- 啟用項(xiàng)目拖拽,需要將視圖的
dragEnable
屬性設(shè)置為true; - 要允許用戶將內(nèi)部或者外部的項(xiàng)目放入視圖中,需要設(shè)置視圖的視口
viewport()
的acceptDrops
屬性為true; - 要顯示現(xiàn)在用戶拖拽的項(xiàng)目將要被放置的位置,需要設(shè)置
showDropIndicator
屬性;
如下:
////// 在視圖項(xiàng)目中啟用拖放功能///listWidget.setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); // 設(shè)置單選模式listWidget.setDragEnabled(true); // 啟用拖拽listWidget.viewport()->setAcceptDrops(true); // 設(shè)置接受拖放listWidget.setDropIndicatorShown(true); // 設(shè)置顯示將要被放置的位置listWidget.setDragDropMode(QListWidget::InternalMove); // 設(shè)置拖放模式為移動項(xiàng)目,如果不設(shè)置,默認(rèn)為復(fù)制項(xiàng)目treeWidget.setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); // 設(shè)置單選模式treeWidget.setDragEnabled(true); // 啟用拖拽treeWidget.viewport()->setAcceptDrops(true); // 設(shè)置接受拖放treeWidget.setDropIndicatorShown(true); // 設(shè)置顯示將要被放置的位置treeWidget.setDragDropMode(QTreeWidget::InternalMove); // 設(shè)置拖放模式為移動項(xiàng)目,如果不設(shè)置,默認(rèn)為復(fù)制項(xiàng)目tableWidget.setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); // 設(shè)置單選模式tableWidget.setDragEnabled(true); // 啟用拖拽tableWidget.viewport()->setAcceptDrops(true); // 設(shè)置接受拖放tableWidget.setDropIndicatorShown(true); // 設(shè)置顯示將要被放置的位置tableWidget.setDragDropMode(QTableWidget::InternalMove); // 設(shè)置拖放模式為移動項(xiàng)目,如果不設(shè)置,默認(rèn)為復(fù)制項(xiàng)目
2. 在模型/視圖類中啟用拖放
在視圖中啟用拖放功能與在便捷類中的設(shè)置相似。如下:
////// 模型/視圖中啟用拖放功能///listView->setSelectionMode(QAbstractItemView::SingleSelection); // 設(shè)置單選模式listView->setDragEnabled(true); // 啟用拖放功能listView->setAcceptDrops(true); // 接受拖放listView->setDropIndicatorShown(true); // 顯示要被放置的位置
自定義模型中的flags()函數(shù)要提供對于拖放操作的支持,即需要增加Qt::ItemIsDragEnabled
和Qt::ItemIsDropEnabled
標(biāo)志。
由于視圖中顯示的數(shù)據(jù)是由模型控制的,也要為使用的模型提供拖放操作的支持。需要重新實(shí)現(xiàn)一些必要的函數(shù)。如下:
// 設(shè)置支持的拖拽動作Qt::DropActions supportedDropActions() const override;// 設(shè)置在拖放操作中導(dǎo)出的條目的數(shù)據(jù)的編碼類型QStringList mimeTypes() const override;// 將拖放的數(shù)據(jù)放入QMimeData中QMimeData *mimeData(const QModelIndexList &indexes) const override;// 將拖放操作的數(shù)據(jù)放入模型中bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
這些函數(shù)的實(shí)現(xiàn)代碼如下:
/*設(shè)置支持使用拖放進(jìn)行復(fù)制和移動兩種操作*/
Qt::DropActions StringListModel::supportedDropActions() const
{return Qt::CopyAction | Qt::MoveAction; // 設(shè)置模型支持拖拽時的移動和復(fù)制操作/** 要允許Qt::MoveAction,模型需要實(shí)現(xiàn)removeRows()函數(shù)*/
}
/*在拖放操作中的數(shù)據(jù)項(xiàng)從模型中導(dǎo)出時,要被編碼為合適的格式來對應(yīng)一個或多個MIME類型,
如下自定義了一個類型,僅支持純文本類型*/
QStringList StringListModel::mimeTypes() const
{QStringList types;// application/vnd.text.list為自定義的類型,后續(xù)需要保持一致types << "application/vnd.text.list";return types;
}
/*進(jìn)行拖放操作之前,需要將數(shù)據(jù)放入到一個QMimeData類型的對象中,
如下使用自定義的格式,將所有要拖拽的數(shù)據(jù)都放入一個QMimeData對象中*/
QMimeData *StringListModel::mimeData(const QModelIndexList &indexes) const
{QMimeData *mimeData = new QMimeData;QByteArray encodedData;QDataStream stream(&encodedData, QDataStream::WriteOnly);//根據(jù)傳入的indexes獲取到所有的文本數(shù)據(jù)foreach (const QModelIndex &index, indexes) {if(index.isValid()){QString text = data(index, Qt::DisplayRole).toString();stream << text;}}// 將數(shù)據(jù)放入QMimeData中mimeData->setData("application/vnd.text.list", encodedData);return mimeData;
}bool StringListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{// 如果是 Qt::IgnorAction,直接返回trueif(action == Qt::IgnoreAction)return true;// 如果數(shù)據(jù)不是指定的格式,返回falseif(!data->hasFormat("application/vnd.text.list"))return false;// 該模型是列表模型,只有一列,判斷列是否正確if(column>0)return false;// 設(shè)置開始插入的行int beginRow=0;if(row != -1)beginRow = row;else if(parent.isValid())beginRow = parent.row();elsebeginRow = rowCount(QModelIndex());// 從data中讀取數(shù)據(jù)QByteArray encodedData = data->data("application/vnd.text.list");QDataStream stream(&encodedData, QDataStream::ReadOnly);QStringList newItem;int rows=0;while (!stream.atEnd()) {QString text;stream >> text;newItem << text;++rows;}insertRows(beginRow, rows, QModelIndex());foreach (const QString &text, newItem) {QModelIndex idx = index(beginRow, 0, QModelIndex());setData(idx, text);beginRow++;}return true;
}
任何給定的模型處理放入數(shù)據(jù)的方式都依賴于它們的類型和向用戶展現(xiàn)的方式。
一般應(yīng)該使用最適合模型底層數(shù)據(jù)存儲的方式來容納放入的數(shù)據(jù)。不同類型的模型會使用不同的方式來處理放入的數(shù)據(jù)。
列表和表格模型只提供了一個平面結(jié)構(gòu)來存儲數(shù)據(jù)項(xiàng),結(jié)果是可能會在當(dāng)數(shù)據(jù)放入一個視圖中的已經(jīng)存在的項(xiàng)目時插入新的行或列,或者會使用提供的數(shù)據(jù)來覆蓋已經(jīng)存在的項(xiàng)目的內(nèi)容。
樹模型一般會在底層數(shù)據(jù)存儲中添加包含新的數(shù)據(jù)的子項(xiàng)。
最后還需要更新flags()函數(shù),用于提供合適的標(biāo)志向視圖表明哪些項(xiàng)目是可以被拖拽的、哪些項(xiàng)目是可以接受放入的。
在自定義模型中實(shí)現(xiàn)視圖中的項(xiàng)的拖放代碼參考:https://github.com/Innern/Qt/tree/master/ModelView/Examples/01_AddressBooks,該項(xiàng)目參考了官方示例Address Books Example,但是增加了對視圖中的項(xiàng)的拖放的支持。
如下:
需要注意的是:
- mimeData()函數(shù)的參數(shù)indexes包含所有選擇拖放的項(xiàng)的索引。比如,
- 如果是簡單的列表視圖,只有一列,選擇拖放時只選擇了一行,那么indexes中包含一個索引,即這一行的索引。
- 如果是表格視圖,有兩列,選擇拖放時選擇一行,那么indexes中包含兩個索引,即這一行的每一列的索引。