QT界面 使用QStyledItemDelegate QPainter QStyleOptionViewItem QModelIndex组合实现项的绘制
QStyledItemDelegate类为来自模型的数据项提供了显示和编辑工具。 当在Qt项视图(例如QTableView)中显示来自模型的数据时,各个项由委托(delegate)绘制。此外,当编辑一个项目时,它提供一个编辑器小部件,当编辑发生时,该小部件放在项目视图的顶部。QStyledItemDelegate是所有Qt项视图的默认委托,在创建时安装在它们上。 QStyledItemDelegate类是模型/视图类之一,是Qt模型/视图框架的一部分。委托允许独立于模型和视图开发项目的显示和编辑。 项目的数据在模型中被分配一个ItemDataRole;每个项目可以为每个角色存储QVariant。QStyledItemDelegate实现显示和编辑用户所期望的最常见的数据类型,包括布尔值、整数、字符串。根据数据在模型中所扮演的角色,数据的绘制将会有所不同。通常需要确保模型为每个角色返回适当的数据,以确定视图中的项的外观。 |
这里有以下几个要点要记住:
1.QStyledItemDelegate是专门用于项的(item)的视图委托!不能作为其他非项的委托使用。
2.委托用于实现个性化设置的项显示,他的数据来源于模型(model),控制view显示的方式。
3.QStyledItemDelegate是作为默认项委托使用的。如果不独立实现并制定项的委托,则在自定义view和自定义的model中使用默认的委托(delegate)。
4.使用默认委托时,从模型中读取的数据都是按照默认规则来的。默认规则就是通过itemDataRole角色标志的数据在view中显示的。因此需要在model中未每个定义的角色返回合适的数据,这样在使用默认委托时才能显示出自己想要的效果。当然,如果想要其他个性化效果最好是使用自定义的委托。
模型中角色可接受的数据类型
角色描述 | 角色 | 可接受的数据类型 |
用于呈现的项目的背景刷(使用默认委托) | Qt::BackgroundRole | QBrush |
这个角色已经过时了。使用BackgroundRole | Qt::BackgroundColorRole | QColor (不再推荐; 可以使用 Qt::BackgroundRole 替代这个角色) |
此角色用于获取项的检查状态 | Qt::CheckStateRole | Qt::CheckState |
以图标的形式作为装饰的数据 | Qt::DecorationRole | QIcon, QPixmap, QImage 和 QColor |
以文本形式呈现的关键数据 | Qt::DisplayRole | QString 或可以返回字符串表示的类型 |
适合编辑器中编辑的格式中的数据 | Qt::EditRole | 详情请看QItemEditorFactory |
项目使用的字体渲染(使用默认委托) | Qt::FontRole | QFont |
将提供给视图的项的大小提示 | Qt::SizeHintRole | QSize |
呈现的项的文本对齐方式(使用默认委托) | Qt::TextAlignmentRole | Qt::Alignment |
前景画笔(通常是文本颜色),(用于使用默认委托呈现的项目) | Qt::ForegroundRole | QBrush |
这个角色已经过时了。使用ForegroundRol | Qt::TextColorRole | QColor (不再推荐; 可以使用 Qt::ForegroundRole 替代这个角色) |
这里注意一下几点:
1.角色的数据大多数在默认委托中有专门的用途(在view中什么以model的什么数据呈现)
2.对于Qt::EditRole我们要特别注意,编辑器是悬浮在item上的一个特别的可编辑按钮,他不属于view视图本身:
编辑器是用QItemEditorFactory创建的;QItemEditorFactory提供的默认静态实例安装在所有项委托上。您可以使用setItemEditorFactory()设置自定义工厂,或者使用QItemEditorFactory::setDefaultFactory()设置一个新的默认工厂。使用编辑的EditRole存储在项目模型中的数据。请参阅QItemEditorFactory类,了解项目编辑器工厂的更高级介绍。 |
使用QStyledItemDelegate的子类实现自定义项的委托
如果委托不支持绘制所需的数据类型,或者希望定制项目的绘制,则需要子类化QStyledItemDelegate,并重新实现paint()和sizeHint()。paint()函数为每个项目分别调用,使用sizeHint(),可以为每个项目指定提示。
当重新实现paint()时,通常会处理要绘制的数据类型,并对其他类型使用超类实现(一般使用QStyledItemDelegate)。
复选框指示符的绘制按当前样式执行。样式还指定用于绘制不同数据角色的数据的大小和边框。项目本身的边框也由样式计算。当绘制已经支持的数据类型时,最好询问这些边框的样式。QStyle类描述更详细地描述了这一点。
如果您希望更改按样式或复选框指示符绘制的任何边框,您可以对QStyle进行子类化。但是,请注意,重新实现sizeHint()也会影响项目的大小。
自定义委托可以在不使用编辑器项目工厂的情况下提供编辑器。在这种情况下,必须重新实现以下虚拟功能:
createEditor()返回用于从模型中更改数据的小部件,并可以重新实现以自定义编辑行为。 |
注意:从Qt 4.4开始,有两个委托类:QItemDelegate和QStyledItemDelegate。但是,默认的委托是QStyledItemDelegate。这两个类是绘制和为视图中的项目提供编辑器的独立替代。它们之间的区别在于,QStyledItemDelegate使用当前样式来绘制其项目。因此,我们建议在实现自定义委托或使用Qt样式表时使用QStyledItemDelegate作为基类。这两个类所需的代码应该是相等的,除非自定义委托需要使用绘图的样式。如果您希望定制项目视图的绘画,您应该实现自定义样式。即QStyle类。
下面就通常需要覆写的方法进行说明
void QStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
重新实现从QAbstractItemDelegate:paint()。使用给定的painter和style选项为索引指定的项呈现委托。这个函数使用视图的QStyle绘制项。在子类中重新实现绘制时。使用initStyleOption()以与QStyledItemDelegate相同的方式设置该选项。只要有可能,在绘画的时候使用这个选项。特别是它的rect变量决定在何处绘制和它的状态,以确定是否启用或选择了它。paint绘画完成后,你应该确保paint回到使用前的状态。例如,在绘制之前调用QPainter::save(),然后调用QPainter: restore()。
注意:
1.QPainter类:QPainter提供了高度优化的函数来完成大多数GUI绘图程序所需的工作。它可以画出从简单的线条到复杂的形状,比如派和和弦。它还可以绘制对齐的文本和像素地图。通常,它画一个“自然”的坐标系统,但它也可以做视图和世界变换。QPainter可以对任何继承QPaintDevice类的对象进行操作。QPainter的常见用法是在小部件的绘图事件中:构造和定制(例如,设置钢笔或画笔)。然后画。记住在画完后要毁掉QPainter对象。
2.QStyleOptionViewItem类:QStyleOptionViewItem类用于描述用于在视图小部件中绘制项的参数。 QStyleOptionViewItem包含QStyle函数绘制Qt模型/视图类项所需的所有信息。由于性能原因,对成员变量的访问是直接的(即。,使用。或- >操作符,都定义为public公有类型)。这种低级的感觉使结构易于使用,并强调这些只是样式函数使用的参数。
3.QModelIndex类:QModelIndex类用于定位数据模型中的数据。这个类被用作从QAbstractItemModel派生的项目模型的索引。项视图、委托和选择模型使用索引来定位模型中的项。
QStyleOptionViewItem类公有区域属性的说明
QModelIndex类的说明
QModelIndex类用于定位数据模型中的数据。这个类被用作从QAbstractItemModel派生的项目模型的索引。项视图、委托和选择模型使用索引来定位模型中的项。新的QModelIndex对象由模型使用QAbstractItemModel::createIndex()函数创建。可以使用QModelIndex构造函数构造无效的模型索引。当引用模型中的*项时,无效索引通常用作父索引。
模型索引引用模型中的项目,并包含在这些模型中指定它们的位置所需的所有信息。每个索引位于给定的行和列中,并且可能具有父索引;使用row()、列()和父()来获取这些信息。模型中的每个*项都由没有父索引的模型索引表示——在本情况下:parent()将返回一个无效的模型索引,相当于使用QModelIndex()构造函数的零参数形式构造的索引。
为了获得一个模型索引,它引用模型中的现有项目,调用QAbstractItemModel::索引(),其中包含所需的行和列值,以及父类的模型索引。当在模型中引用*项时,供应QModelIndex()作为父索引。
注意:应该立即使用模型索引,然后丢弃。在调用修改模型结构的模型函数或删除项之后,不应该依赖索引来保持有效。如果需要长期保持模型索引,请使用QPersistentModelIndex。