QTreeview 重写Model 与 Item 理解

view(如QTreeview) / Model / 数据之间的交互。 View与数据是分离的,数据通过Model进行管理。View 通过调用Model来访问数据。

一、 QTreeView的简单使用,可以如下

QTreeView使用总结1,一个简单示例        这个就是简单的显示。

QTreeView使用总结2,常用API介绍        比如选择,自适应宽度啊...

常用的设置API:
QTreeView* t;
// ------ 表头和列 ------
t->header()->hide();                                    // 隐藏表头
t->header()->setDefaultSectionSize(100);                // 设置默认列宽
t->header()->setDefaultAlignment(Qt::AlignCenter);      // 设置表头默认文字对齐
// 一般设置最后一列自适应宽度,让表头初始显示时占满行,效果比较好:
t->header()->setStretchLastSection(true);
// 点击QTreeView时,如果出现该列头文字加粗的情况,可以用下面接口去掉该属性:
t->header()->setHighlightSections(true);
// 当然,项目里的做法一般更细节,可能是对每列分别设置列宽、拉伸属性:
t->header()->resizeSection(0,100);                            //第1列宽100
t->header()->setSectionResizeMode(3,QHeaderView::Fixed);      //第4列定宽
也可以直接使用QTreeView的接口设置列宽:
void setColumnWidth(int column, int width);
设置QTreeView内容按某列排序:
t->header()->setSortIndicator(0,Qt::AscendingOrder);          //按第1列升序排序

// ------ 行 ------
// 设置行高:
// QTreeView没有直接提供设置行高的方法,一般的方法是使用Delegate。
// 从QItemDelegate继承,使用QTreeView::setItemDelegate设置。派生类里对sizeHint处理:
QSize MyDelegate::sizeHint ( const QStyleOptionViewItem & option,  const QModelIndex & index ) const  
{  
    QSize size = QItemDelegate::sizeHint(option, index);  
    size.setHeight( size.height() + 4 );  
    return size;  
}  
// 我觉得最简单的方法就是直接用qss样式表:
QTreeView::item {
	height: 30px;
}

二、 Model/View框架介绍

Model/View框架介绍

三、QTreeView的选中信号处理

QTreeView使用总结5,选中信号处理

四、单击双击的信号与事件

QTreeView使用总结6,单击双击的信号与事件

五、右键菜单

QTreeView使用总结7,右键菜单

六、使用委托,定制item

QTreeview 和 Model 之间进行交互。它们是通过 Delegate进行的,没有设置delegate的话,使用的就是默认的 QItemDelegate委托【代码处理逻辑中保存的是QTreeviewPrivate中的是QItemDelegate的基类QAbstractItemDelegate,QAbstractItemDelegate基本为空,具体默认实现就是 QItemDelegate: QAbstractItemDelegate是一个抽象基类】

对上面描述的进一步补充

我们也可以通过setDelegate 来设置我们自己写的delegate

继承QStyledItemDelegate,写一个MyDelegate类:

实现里面的以下方法:
createEditor: 当item激活编辑状态时,显示的内容。这里创建一个QComboBox
setEditorData:用以初始化createEditor里创建的控件内容。这里直接把当前item的text设置为QComboBox选中项。
setModelData:应用编辑后,修改model的data。这里把QComboBox的当前选中项文本设置为item的显示文本。
updateEditorGeometry:更新控件位置状态。

QTreeView使用总结9,使用委托,定制item输入效果

QTreeView使用总结10,使用委托,定制item显示效果 : 这个主要是重写委托的paint函数

七、使用代理model 对基础model功能进一步扩展(比如过滤功能)

代理model 相当于在基础model之外又套了一层,对model 进行了功能扩展,它还是通过model来进行访问数据

QTreeView使用总结11,数据过滤,使用代理model,简单过滤

QTreeView使用总结12,数据过滤,代理model,自定义过滤条件        自定义代理model

八、自定义model

一般树形视图,我们使用的model是QStandardItemModel,基本上就够了,那为什么要自定义model呢,就是特殊功能+性能

前面简单介绍过Qt的模型/视图框架,提到了Qt预定义的几个model类型:
QStringListModel:存储简单的字符串列表
QStandardItemModel:可以用于树结构的存储,提供了层次数据
QFileSystemModel:本地系统的文件和目录信息
QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel:存取数据库数据

一般情况下满足需求了,不过有时候需要一些定制功能,或者是大量数据下对性能和开销比较注重,觉得自带的model无用功能太多效率比较低,这时候自定义model就比较适合了。
我使用自定义model 同时出于这两方面需要,既为了性能也为了特殊功能。

QTreeView使用总结13,自定义model示例,大大优化性能和内存

使用自定义model 的时候,一般也会实现 们自定义的指代一个节点的类 TreeItem。详细看下上面的例子。

深入理解一下为什么 优化了内存。。。

QTreeView使用总结14,自定义model,控制对齐和颜色

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

QTreeView使用总结16,定时刷新后,当前选中行的处理

在使用QTreeView展示数据的时候,有些数据是在动态变化的,
这时候也需要动态刷新界面,一般直接更新model即可。
但是存在一个问题:之前的选中状态会丢失。
本文讨论在更新数据时如何处理选中状态。

QTreeView使用总结17:改造QTreeView,实现点击空白处取消选中

QTreeView使用总结18:点击空白处取消选中,简单方法  我还是觉得第一个方法更好

QTreeView使用总结19,添加、删除、清空功能示例

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在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就可以显示自定义数据了。您可以根据自己的需求扩展并修改此示例代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值