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);
        }
    }
}

这样就实现了不同按钮点击和响应的的功能;

 

posted @ 2024-09-14 16:45  一字千金  阅读(108)  评论(0编辑  收藏  举报