QTreeView代理QStyledItemDelegate实现按钮的鼠标hover移动和点击响应
1.需求描述
QStyledItemDelegate实现按钮的点击和响应功能,鼠标移动到按钮上,也会显示tooltip提示信息
2.实现方法
(1)重写editorEvent函数,根据type类型触发不同的响应函数
为了实现按钮的响应,需要重写QStyledItemDelegate 类的editorEvent函数,并根据插入时设置进去的type类型,判断是什么类型,然后去触发不同鼠标消息。
bool TreeTaskDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { //QMouseEvent *pEvent = static_cast<QMouseEvent *> (event); //m_mousePoint = pEvent->pos(); bool ret = false; // 还原鼠标样式 QApplication::restoreOverrideCursor(); QVariantMap var = index.data(Qt::UserRole).toMap(); if (var.contains("type")) { QString strType = var.value("type").toString(); if (strType == "0") { ret=TriggerCase(event, model, option,index); } else if (strType == "1") { ret=TriggerFolder(event, model, option, index); } else if (strType == "3") { ret=TriggerCamera(event, model, option, index); } else if (strType == "2") { ret=TriggerVideo(event, model, option, index); } } return QStyledItemDelegate::editorEvent(event, model, option, index); }
(2)根据坐标和鼠标消息类型响应不同的鼠标消息
还是以案件的触发来举例说明如何实现,根据绘制的按钮的坐标数据(要和paintCase函数中的按钮坐标一致),当鼠标在绘制的按钮矩形上移动时,触发QEvent::MouseMove信号,显示tooltips提示信息,一定要将QTreeView的mousetracing属性设置为true,否则无法触发QEvent::MouseMove信号;
点击按钮时触发MouseButtonRelease信号,根据坐标矩形区域判断是否点击了哪个按钮,向外发送按钮点击信号;
bool TreeTaskDelegate::TriggerCase(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { bool ret = true; QMouseEvent *pEvent = static_cast<QMouseEvent *> (event); if (pEvent == NULL) { return true; } QVariantMap info = index.data(Qt::UserRole).toMap(); m_mousePoint = pEvent->pos(); QRect rectItem = option.rect; QRect rectTop = QRect(rectItem.x() + 75, rectItem.y() + 8, 24, 24); QRect rectEdit = QRect(rectItem.x() + 95, rectItem.y() + 8, 24, 24); QRect rectCreateDir = QRect(rectItem.x() + 125, rectItem.y() + 8, 24, 24); QRect rectInput = QRect(rectItem.x() + 155, rectItem.y() + 8, 24, 24); QRect rectDelete = QRect(rectItem.x() + 185, rectItem.y() + 8, 24, 24); QRect rectState = QRect(rectItem.x() + 210, rectItem.y() + 10, 54, 20); QRect nameRect = QRect(rectItem.x() + 44, rectItem.y() + 8, 20, 24); switch (pEvent->type()) { case QEvent::MouseButtonRelease: if (rectTop.contains(m_mousePoint)) { emit signalBtClicked("0", "Top", index); } else if (rectEdit.contains(m_mousePoint)) { emit signalBtClicked("0", "Edit", index); } else if (rectCreateDir.contains(m_mousePoint)) { emit signalBtClicked("0", "CreateDir", index); } else if (rectInput.contains(m_mousePoint)) { emit signalBtClicked("0", "Input", index); } else if (rectDelete.contains(m_mousePoint)) { emit signalBtClicked("0", "Delete", index); } else if (rectState.contains(m_mousePoint)) { emit signalBtClicked("0", "State", index); } break; case QEvent::MouseMove: { if (rectTop.contains(m_mousePoint)) { if (info.contains("top") && info.value("top").toString() == "1") { QToolTip::showText(pEvent->globalPos(), "取消置顶"); } else { QToolTip::showText(pEvent->globalPos(), "置顶"); } } else if (rectEdit.contains(m_mousePoint)) { QToolTip::showText(pEvent->globalPos(), "重命名"); } else if (rectCreateDir.contains(m_mousePoint)) { QToolTip::showText(pEvent->globalPos(), "创建子文件夹"); } else if (rectInput.contains(m_mousePoint)) { QToolTip::showText(pEvent->globalPos(), "导入"); } else if (rectDelete.contains(m_mousePoint)) { QToolTip::showText(pEvent->globalPos(), "删除"); } else if (rectState.contains(m_mousePoint)) { emit signalBtClicked("0", "State", index); } else if (nameRect.contains(m_mousePoint)) { QToolTip::showText(pEvent->globalPos(), info.value("name").toString()); } break; } } return ret; }
(3)连接代理的鼠标点击信号和组织树的响应函数
connect(m_TreeDelegate, &TreeTaskDelegate::signalBtClicked, this, &TreeTaskList::SlotTreeBtClicked);
(4)实现按钮点击响应函数
根据delegate类传过来的信号type判断是案件、文件夹、监控点、视频任务;根据按钮类型判断是置顶、导入、删除等按钮;然后去处理不同的消息;
void TreeTaskList::SlotTreeBtClicked(QString type, QString bt, const QModelIndex &index) { QVariantMap caseinfo = index.data(Qt::UserRole).toMap(); QStandardItem*pItem = caseinfo.value("treeItem").value<QStandardItem*>(); if (pItem==NULL) { LOG_ERROR("Btn Click pitem is NULL"); return; } if (type=="0")//案件 { if (bt== "Top") { QString strTop =caseinfo.value("top").toString(); if (strTop=="1")//取消置顶 { caseinfo.insert("top", "0"); QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); caseinfo.insert("createtime", strTime); pItem->setData(strTime, QOrderRole); QString strSql = QString("update CaseManage set createtime = '%1' ,top='0' where path='%2'").arg(strTime).arg(caseinfo.value("path").toString()); QString strmsg = ""; QVariantMap result; LocalDb::instance()->ExcuateSql(strSql, result, strmsg); if (m_picPathDirInfo.find(caseinfo.value("path").toString()) != m_picPathDirInfo.end()) { m_picPathDirInfo[caseinfo.value("path").toString()]["createtime"] = strTime; m_picPathDirInfo[caseinfo.value("path").toString()]["top"] = "0"; } pItem->setData(caseinfo, Qt::UserRole); } else//置顶 { caseinfo.insert("top", "1"); //增加100年作为置顶时间排序最上面 QString strTime = QDateTime::currentDateTime().addYears(100).toString("yyyy-MM-dd hh:mm:ss.zzz"); caseinfo.insert("createtime", strTime); pItem->setData(strTime, QOrderRole); QString strSql = QString("update CaseManage set createtime= '%1' , top='1' where path='%2'").arg(strTime).arg(caseinfo.value("path").toString()); QString strmsg = ""; QVariantMap result; LocalDb::instance()->ExcuateSql(strSql, result, strmsg); if (m_picPathDirInfo.find(caseinfo.value("path").toString()) != m_picPathDirInfo.end()) { m_picPathDirInfo[caseinfo.value("path").toString()]["createtime"] = strTime; m_picPathDirInfo[caseinfo.value("path").toString()]["top"] = "1"; } pItem->setData(caseinfo, Qt::UserRole); } SlotUpdateTreeListBackground(); m_modelTree->sort(0, Qt::DescendingOrder); } else if (bt== "Edit") { caseinfo.insert("editing", "Edit"); pItem->setData(caseinfo, Qt::UserRole); ui.treeView->openPersistentEditor(index); } else if (bt== "CreateDir") { AddEmptyFoldToList(pItem); QModelIndex index = m_modelTree->indexFromItem(pItem); if (index.isValid()) { ui.treeView->expand(index); } } else if (bt== "Input") { if (m_bAddingTaskToList) { emit signalError(-3, "正在批量导入任务,导入过程中不可用,请稍后重试"); return; } m_pCurrentItem = pItem; if (m_pCurrentItem) { QString strParantPath = m_pCurrentItem->data(Qt::UserRole).toMap().value("path").toString(); QString strType = m_pCurrentItem->data(Qt::UserRole).toMap().value("type").toString(); if (strType == "0" || strType == "1") { DLMgr::instance()->Fun_SetCurrentItemPath(strParantPath); } } m_iaddType = 1; emit signalAddAnaClicked(m_iaddType); } else if (bt== "Delete") { ConfirmDialog dig("删除案件将清空相关的数据和图片,确认删除?"); if (dig.exec() == QDialog::Rejected) { return; } UpdateChildCheckState(pItem, true); QStringList listDelPicPath; QMap<QString, QVariantMap>taskInfos; BatchRecursiveDeleteItem(pItem, listDelPicPath, taskInfos); QString strPath = caseinfo.value("path").toString(); if (strPath != "") { listDelPicPath.push_back(strPath); m_picPathDirInfo.remove(strPath); } DeleteCaseThread* pDelThread = new DeleteCaseThread(); connect(pDelThread, &DeleteCaseThread::finished, pDelThread, [=]() { SlotUpdateTreeListBackground(); UpdateAllCasesStatistic(); pDelThread->deleteLater(); emit signalSelectVedioChanged(m_mapStrFileSelected); }); connect(pDelThread, SIGNAL(signalDelCollisionTask(QString)), this, SLOT(SlotDelCollisionTask(QString))); connect(pDelThread, &DeleteCaseThread::signalDeleteProgress, &m_progressDialog, &ProgressDialog::SlotDeleteProgress); pDelThread->SetDeleteCases(listDelPicPath, taskInfos); m_progressDialog.SlotDeleteProgress(0); m_progressDialog.exec(); if (index.isValid()) { m_modelTree->removeRow(index.row()); } SlotUpdateTreeListBackground(); UpdateAllCasesStatistic(); emit signalSelectVedioChanged(m_mapStrFileSelected); } else if (bt== "State") { TasksStatistic taskState = caseinfo.value("TasksStatistic").value<TasksStatistic>(); m_CaseStateWidget.SetTasksStatistic(taskState); QPoint Point = QCursor::pos(); m_CaseStateWidget.move(Point.x() + 10, Point.y() + 10); m_CaseStateWidget.hide();//先隐藏再显示,否则会出现在下面; m_CaseStateWidget.show(); m_CaseStateWidget.setFocus(Qt::FocusReason::ActiveWindowFocusReason); } } }
这样就实现了不同按钮点击和响应的的功能;
自己开发了一个股票智能分析软件,功能很强大,需要的关注微信公众号:QStockView