QTreeView使用总结15,自定义model,支持item可编辑

1,简介

之前发布的两篇自定义model的文章,有小伙伴下载源码后发现元素不能编辑。

确实是的,因为我自己都是用来展示数据,没做这个。

这篇文章实现item编辑功能。

2,效果

但是由于我这个示例,真实数据只有名称、三门课成绩,后面的展示数据都是根据这些实时计算出来的。

因此只有真实数据支持修改,而且修改后 其他推算型数据也会自动刷新。

这点需要注意。

3,代码

主要需处理下面几个地方:

1,QTreeView 也要设置编辑操作类型:

ui->treeView->setEditTriggers(QTreeView::DoubleClicked);			//单元格双击编辑

2,元素的 flags 要加可编辑属性: Qt::ItemIsEditable

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    //节点是否允许编辑
    Qt::ItemFlags flags = QAbstractItemModel::flags(index);
    flags |= Qt::ItemIsEditable;
    
    return flags;
}

3,另外data 函数里,也需要对 Qt::EditRole 处理下,否则打开编辑框时,默认是空白。

这里我们让编辑框默认就显示 item 的文本。

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
    if (role == Qt::DisplayRole)
    {
        return item->data(index.column());
    }
    else if (role == Qt::EditRole)
    {
        //元素打开编辑框时,显示的内容,如果没有这行,编辑框出现时默认为空白
        return item->data(index.column());
    }
    else if( role == Qt::TextAlignmentRole )
    {
        if( index.column() == 0 )
        {
            //第1列左对齐
            return QVariant(Qt::AlignVCenter | Qt::AlignLeft);
        }
        else if( index.column() > 0 && index.column() < 6 )
        {
            //第2~6列右对齐
            return QVariant(Qt::AlignVCenter | Qt::AlignRight);
        }
        else
        {
            //其他列居中对齐
            return QVariant(Qt::AlignCenter);
        }
    }
    else if(role == Qt::TextColorRole)
    {
        if(index.column() == 6)
        {
            QString str = item->data(6).toString();
            if(str == QStringLiteral("不合格"))
            {
                //第7列(是否合格)如果不合格就设文本为红色
                return QVariant(QColor("#FF0000"));
            }
        }
        return QVariant();
    }
    return QVariant();
}

4,setData 函数,就是编辑框输入完后,应用时走的逻辑,我们去修改真实数据:

bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole)
    {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        item->setData(index.column(), value);

        emit dataChanged(index, index);
        return true;
    }
    return false;
}

其中调用TreeItem 进行真正的修改:

可以看到真实数据只有这几个,因此也只能修改这几个数据。其他数据会在显示时自动计算的。

void TreeItem::setData(int column, QVariant value)
{
    if(mLevel == 1)
    {
        //一级节点,班级
        if(column == 0)
        {
            CLASS* c = (CLASS*)mPtr;
            c->name = value.toString();
        }
    }
    else if(mLevel==2)
    {
        //二级节点学生信息
        STUDENT* s = (STUDENT*)mPtr;
        switch (column)
        {
        case 0: s->name = value.toString();break;
        case 1: s->score1 = value.toInt();break;
        case 2: s->score2 = value.toInt();break;
        case 3: s->score3 = value.toInt();break;

        default:
            return ;
        }
    }
}

4,源码


写作不易,源码有偿提供:(注意链接是全套专栏完整源码,请勿重复下载)

https://mianbaoduo.com/o/bread/YZuTk5dx

欢迎入群交流:
群号码:1149411109 (若满加2群:917341904)
群名称:Qt实战派学习群

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在PyQt6中,可以使用自定义的模型来在QTreeView中显示数据。下面是一个使用自定义模型的示例代码。 ```python from PyQt6.QtCore import QAbstractItemModel, QModelIndex, Qt from PyQt6.QtWidgets import QApplication, QMainWindow, QTreeView class CustomModel(QAbstractItemModel): def __init__(self, data, parent=None): super().__init__(parent) self.rootItem = CustomItem(None, None) self.setupModelData(data, self.rootItem) def setupModelData(self, data, parent): for item in data: parent.appendChild(item) def index(self, row, column, parent=QModelIndex()): if not self.hasIndex(row, column, parent): return QModelIndex() if not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() childItem = parentItem.child(row) if childItem: return self.createIndex(row, column, childItem) else: return QModelIndex() def parent(self, index): if not index.isValid(): return QModelIndex() childItem = index.internalPointer() parentItem = childItem.parent() if parentItem == self.rootItem: return QModelIndex() return self.createIndex(parentItem.row(), 0, parentItem) def rowCount(self, parent=QModelIndex()): if parent.column() > 0: return 0 if not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() return parentItem.childCount() def columnCount(self, parent=QModelIndex()): if parent.isValid(): return parent.internalPointer().columnCount() else: return self.rootItem.columnCount() def data(self, index, role=Qt.ItemDataRole.DisplayRole): if not index.isValid(): return None item = index.internalPointer() if role == Qt.ItemDataRole.DisplayRole: return item.data(index.column()) elif role == Qt.ItemDataRole.TextAlignmentRole: return Qt.AlignmentFlag.AlignVCenter + Qt.AlignmentFlag.AlignLeft def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole): if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole: return self.rootItem.data(section) def flags(self, index): if not index.isValid(): return Qt.ItemFlag.NoItemFlags return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable class CustomItem: def __init__(self, data, parent): self.parentItem = parent self.itemData = data self.childItems = [] def appendChild(self, item): self.childItems.append(item) def child(self, row): return self.childItems[row] def childCount(self): return len(self.childItems) def columnCount(self): return len(self.itemData) def data(self, column): return self.itemData[column] def parent(self): return self.parentItem if __name__ == "__main__": app = QApplication([]) window = QMainWindow() treeView = QTreeView(window) data = [ CustomItem(["Item 1"], None), CustomItem(["Item 2"], None) ] model = CustomModel(data) treeView.setModel(model) window.setCentralWidget(treeView) window.resize(500, 500) window.show() app.exec() ``` 在这个示例中,定义了一个`CustomModel`类继承自`QAbstractItemModel`类,并重写了一些必要的方法。同时定义了一个`CustomItem`类作为模型的节点数据。 在`CustomModel`中,`index`方法用于获取给定行列的索引,`parent`方法用于获取给定索引的父索引,`rowCount`和`columnCount`方法用于获取给定索引的行数和列数,`data`方法返回指定索引的数据,`headerData`方法返回给定节的标题数据,`flags`方法定义每个索引的标志。 在主函数中,创建一个自定义模型`CustomModel`的实例,并将数据传递给模型。然后将该模型设置为`QTreeView`的模型,最后显示窗口并进入应用程序的事件循环。 这样,使用自定义模型的QTreeView就可以显示自定义数据了。您可以根据自己的需求扩展并修改此示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆枫゛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值