首页 > 其他分享 >QTreeView+QStyledItemDelegate实现编辑名称功能

QTreeView+QStyledItemDelegate实现编辑名称功能

时间:2024-09-14 17:50:47浏览次数:9  
标签:QTreeView caseinfo strType 编辑 名称 pEdit QStyledItemDelegate strNewName QString

1.需求描述

点击编辑按钮,进入编辑状态,点击确认和取消按钮退出编辑状态

(1)   重写代理createEditor函数

这个函数是代理触发编辑信号后,自动创建编辑界面的widget对象,覆盖在item上;EmptyTreeItem就是我们自定义的编辑控件,包括输入框,确认和取消按钮;

QWidget * TreeTaskDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QVariantMap caseinfo = index.data(Qt::UserRole).toMap();
    QString strType = caseinfo.value("type").toString();
    EmptyTreeItem* pEdit = NULL;
    if (strType=="0")//案件
    {
        pEdit = new EmptyTreeItem();
        pEdit->setParent(parent);
        pEdit->SetAddType(TreeItemType::TopCase);
        connect(pEdit, &EmptyTreeItem::signalEditFinish, this, &TreeTaskDelegate::OnEditFinish);
        
    }
    else if (strType=="1")//文件夹
    {
        pEdit = new EmptyTreeItem();
        connect(pEdit, &EmptyTreeItem::signalEditFinish, this, &TreeTaskDelegate::OnEditFinish);
        pEdit->setParent(parent);
        pEdit->SetAddType(TreeItemType::ChildFolder);
    }
    else if (strType == "-1")//新增案件或者文件夹
    {
        pEdit = new EmptyTreeItem();
        connect(pEdit, &EmptyTreeItem::signalEditFinish, this, &TreeTaskDelegate::OnEditFinish);
        pEdit->setParent(parent);
        if (caseinfo.contains("parantItem"))
        {
            pEdit->SetAddType(TreeItemType::ChildFolder);
        }
        else
        {
            pEdit->SetAddType(TreeItemType::TopCase);
        }
        
    }
    return pEdit;
}

(2)   重写代理的setEditorData函数

这个函数的作用是给自定义编辑窗口设置用户数据,例如将编辑前的名称设置给编辑窗口,显示在输入框内,作为初始值;

void TreeTaskDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if (editor==NULL)
    {
        return;
    }
    QVariantMap caseinfo = index.data(Qt::UserRole).toMap();
    QString strType = caseinfo.value("type").toString();
    if (strType == "0" || strType=="1"|| strType=="-1")
    {
        EmptyTreeItem* pEdit = dynamic_cast<EmptyTreeItem*>(editor);
        if (pEdit == NULL)
        {
            return;
        }
        QVariantMap caseinfo = index.data(Qt::UserRole).toMap();
        QString strType = caseinfo.value("type").toString();
        pEdit->setInfo(caseinfo); //将数据设置给编辑窗口,例如显示修改前的名字
    }
}

 

(3)重写代理的updateEditorGeometry函数

这个函数的作用是设置编辑窗口在item上的坐标,我们采用是完全覆盖,所以直接以item的坐标设置给编辑窗口;

void TreeTaskDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //QRect rect(option.rect.x() +20, option.rect.y(), option.rect.width() - 20, option.rect.height());
    editor->setGeometry(option.rect);
}

 

(4)重写代理的setModelData函数

这个函数的作用是编辑完成后将数据再从新更新到model中去,并刷新界面的显示,但是我们还需要更新到数据库,还需要判断有没有重名,所以没有在代理中实现这个函数,而是将通过编辑窗口的确认按钮和取消按钮传出编辑完成的信号出去,用槽函数实现编辑完成后的处理;

//void TreeTaskDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
//{
//    if (editor == NULL||model==NULL)
//    {
//        return;
//    }
//    EmptyTreeItem* pEdit = dynamic_cast<EmptyTreeItem*>(editor);
//    if (pEdit==NULL)
//    {
//        return;
//    }
//    QVariantMap caseinfo = index.data(Qt::UserRole).toMap();
//    QString strType = caseinfo.value("type").toString();
//    caseinfo.insert("name", pEdit->GetName());
//    model->setData(index, caseinfo, Qt::UserRole);
//}

(5)在createEditor函数中创建编辑界面时就连接确认和取消按钮消息

connect(pEdit, &EmptyTreeItem::signalEditFinish, this, &TreeTaskDelegate::OnEditFinish);

(6)代理中实现OnEditFinish函数,传出信号给使用类

void TreeTaskDelegate::OnEditFinish(QString strType, QString strNewName)//strType confirm cancel
{
    QWidget *editor = qobject_cast<QWidget *>(sender());
    emit commitData(editor);
    emit closeEditor(editor);
    EmptyTreeItem* pEdit = (EmptyTreeItem*)(editor);
    if (pEdit!=NULL)
    {
        QVariantMap caseinfo = pEdit->getInfo();
        emit signalEditFinish(caseinfo, strType, strNewName);
    }
    
}

(7)    连接信号并实现编辑完成函数

void TreeTaskList::SlotEditFinish(QVariantMap caseinfo, QString buttontype, QString strNewName)
{    
    strNewName = strNewName.trimmed();
    QStandardItem* pItem = caseinfo.value("treeItem").value<QStandardItem*>();
    if (pItem==NULL)
    {
        return;
    }
    if (caseinfo.contains("type"))
    {
        QString strType = caseinfo.value("type").toString();
        QString strOldName = caseinfo.value("name").toString();
        QString strPath = caseinfo.value("path").toString();
        if (strType == "0")//案件
        {
            if (buttontype == "confirm")
            {
                if (strOldName != strNewName)
                {
                    if (CheckSameName(NULL, strNewName) == 1)
                    {
                        emit signalError(-3, "同级目录下已有重名案件,请重新命名");
                        return;
                    }
                    //将名称更新到数据库
                    QString sql = QString("update CaseManage set name='%1' where path='%2'").arg(strNewName).arg(strPath);
                    QString strMsg = "";
                    if (LocalDb::instance()->ExcuateSql(sql, strMsg) == 0)
                    {
                        caseinfo.insert("name", strNewName);
                    }
                    else
                    {
                        emit signalError(-3, "重命名保存到数据库失败");
                        LOG_ERROR("save name to db failed errormsg: %s", strMsg.toStdString().c_str());
                        return;
                    }
                    SlotResizeTreeWidget();
                }
                
            }
            else if (buttontype == "cancel")
            {
                
            }
            caseinfo.remove("editing");
            m_picPathDirInfo.insert(strPath, caseinfo);
            pItem->setData(caseinfo, Qt::UserRole);
            ui.treeView->closePersistentEditor(m_modelTree->indexFromItem(pItem));
        }
        else if (strType == "1")//文件夹
        {
            
            if (buttontype == "confirm")
            {
                if (strOldName != strNewName)
                {
                    QStandardItem* pParatItem = pItem->parent();
                    if (pParatItem!=NULL)
                    {
                        if (CheckSameName(pParatItem, strNewName) == 1)
                        {
                            emit signalError(-3, "同级目录下已有重名文件夹,请重新命名");
                            return;
                        }
                    }
                    //将名称更新到数据库
                    QString sql = QString("update CaseManage set name='%1' where path='%2'").arg(strNewName).arg(strPath);
                    QString strMsg = "";
                    if (LocalDb::instance()->ExcuateSql(sql, strMsg) == 0)
                    {
                        caseinfo.insert("name", strNewName);
                    }
                    else
                    {
                        emit signalError(-3, "重命名保存到数据库失败");
                        LOG_ERROR("save name to db failed errormsg: %s", strMsg.toStdString().c_str());
                        return;
                    }
                }
            }
            else if (buttontype == "cancel")
            {

            }
            caseinfo.remove("editing");
            m_picPathDirInfo.insert(strPath, caseinfo);
            pItem->setData(caseinfo, Qt::UserRole);
            ui.treeView->closePersistentEditor(m_modelTree->indexFromItem(pItem));
        }
        else if (strType == "-1")//新增案件或者文件夹
        {
            QStandardItem* parantItem = NULL;
            if (caseinfo.contains("parantItem"))
            {
                parantItem = caseinfo.value("parantItem").value<QStandardItem*>();
            }
            if (buttontype == "confirm")
            {
                if (strNewName.trimmed() == "")
                {
                    signalError(-2, "案件名称不能为空或空格,请输入案件名称");
                    return;
                }
                
                if (AddFoldToList(strNewName.trimmed(), parantItem) == NULL)//添加案件
                {
                    //signalError(-2, "添加案件失败");
                    return;
                }
            }
            else if (buttontype == "cancel")
            {

            }
            ui.treeView->closePersistentEditor(pItem->index());
            if (parantItem==NULL)
            {
                m_modelTree->removeRow(pItem->row());
            }
            else
            {
                parantItem->removeRow(pItem->row());
            }
            SlotResizeTreeWidget();    
            m_modelTree->sort(0, Qt::DescendingOrder);
        }
    }
    
}

(8)触发编辑状态和关闭编辑状态

触发编辑状态,点击重命名时调用

ui.treeView->openPersistentEditor(index);//会一致显示,失交也不会退出

关闭编辑状态,编辑结束或者取消时调用

ui.treeView->closePersistentEditor(m_modelTree->indexFromItem(pItem));

 

标签:QTreeView,caseinfo,strType,编辑,名称,pEdit,QStyledItemDelegate,strNewName,QString
From: https://www.cnblogs.com/bclshuai/p/18414429

相关文章

  • QTreeView置顶排序功能实现
    1.需求描述QTreeView先插入的排在上面,并支持手动置顶进行排序,取消置顶;2.实现方案(1)定义排序角色给每一个插入的QStandardItem对象设置一个排序角色,我们用插入时间来设置这个值;enum CustomRole{   QOrderRole=Qt::UserRole+1};构造函数中设置model的排序角色m_......
  • QStandardItem先设置图标再插入QTreeView会影响插入性能
    所有的界面显示都交代理去绘制,否则会影响插入性能;一开始打算将类型图标通过QStandardItem创建时传给QStandardItem,在插入到model中,后来发现这样会降低插入的性能;pItem=newQStandardItem(QIcon(":/foldericon.svg"),info.value("name").toString());改成用代理QStyledItemDel......
  • QTreeView实现搜索功能并且关键字标红
    1、需求描述实现组织树搜索,关键字红色显示;搜索规则,名称匹配显示,没有匹配不显示,子节点匹配,父节点即使没有匹配也显示;2.实现方法(1)top节点名称匹配关键则显示,否则隐藏voidTreeTaskList::SlotFilterChanged(QStringstrText){m_TreeDelegate->setProperty("FilterString"......
  • QTreeView代理QStyledItemDelegate实现按钮的鼠标hover移动和点击响应
    1.需求描述QStyledItemDelegate实现按钮的点击和响应功能,鼠标移动到按钮上,也会显示tooltip提示信息2.实现方法(1)重写editorEvent函数,根据type类型触发不同的响应函数为了实现按钮的响应,需要重写QStyledItemDelegate类的editorEvent函数,并根据插入时设置进去的type类型,判断是......
  • QTreeView代理QStyledItemDelegate实现按钮、图标的绘制
    1.需求描述代理实现按钮图标状态的绘制实现方法(1)重写paint函数,根据type类型绘制案件、文件夹、监控点、视频任务; 为了实现不同的item的样式,需要继承QStyledItemDelegate类型实现TreeTaskDelegate。重写paint函数,根据不同的类型type去绘制不同的按钮和状态;voidTreeTaskD......
  • permission_required 权限需要添加应用名称
    Django之所以能在permission_required='view_customer'中正常判断权限,是因为它在默认情况下使用当前视图所属应用的app_label。如果没有显式指定应用名,Django会假设权限属于当前视图对应的应用。在customers应用中,permission_required='view_customer'能够正常工作,原......
  • uniapp使用路由名称跳转
    由于web端和app公用一套菜单,而两个项目的路径是不同的,为解决这个问题,封装了一套使用路由名称作为跳转路由的方法1.在pages.json文件里pages对应的页面配置里添加routeName字段(自定义),我做的app里面的菜单是后台获取的,所以这里的value值对应的是后台返回的页面路由 2.开始封......
  • POI常见包名称含义,常见HSSF,SXXF,SXSSF区别
    Java单元格合并后边框消失了在使用Java编写Excel文件时,经常会遇到合并单元格的需求。单元格合并可以使表格更加美观,同时减少重复的内容。然而,有时候在合并单元格后会发现边框消失了,这给我们带来了困惑。本文将介绍这个问题的原因以及解决方法,并提供相应的代码示例。问题描述当我......
  • ASP.NET 8 AOT 遍历文件夹获取文件名称及时长
    朋友下了N多视频记不住文件夹下都有啥了…问批处理怎么导出文件夹下所有文件名及视频时长…批处理导出文件名好弄,获取视频时长真没用过…想到.net控制台程序AOT发布,不和批处理差不多效果…新建个控制台项目选下使用AOT首先要获取文件的时长,我们需要用下TagLibSharpInstall-P......
  • vue使用axios实现下载附件以及根据响应头content-disposition,拿到附件名称filename,实
    直接代码exportfunctiondownload(url){returndownloadserviceIGO({url:url,method:'get',responseType:'blob',closeMsg:true,loadingText:true})}/***批量下载附件*/......