•. 概念
•.使用一个已有的代表
•.一个简单的代表
•.提供一个编辑器
•.提交数据到模型
•.更新编辑器的几何属性
•.编辑提示
与模型 -视图-控制器模式不同,模型 /视图设计方式不包含一个完全独立的用来与用户进行交互的组件。通常 ,视图负责将模型数据显示给用户 ,并且处理用户的输入。为了在输入的过程中引入一些灵活性 ,由代表来进行交互 。这些组件提供输入能力并且负责某些视图中的单个条目的渲染。标准的用来控制代表的接口是定义在 QAbstractItemDelegate 类中的 。
代表们 被预期可以自己通过实现 paint() 和 sizeHint() 函数来渲染它们的内容。然而 ,简单的基于部件的代表可以子类化 QItemDelegate ,而不是 QAbstractItemDelegate ,以利用这些函数的默认实现。
代表的编辑器可能通过使用部件来管理编辑过程或者通过直接处理事件来实现 。第一种实现方式在这一 章的后面讲述,并且也在旋转 框代表那个 示例中展示 。
Pixelator 那个示例展示了如何创建一个为表格视图进行特殊渲染的自定义代表 。
Qt 提供的标准视图使用 QItemDelegate 的实例来提供编辑设施 。这种代表的默认接口按照每种标准视图的常用风格来渲染条目 : QListView , QTableView 和 QTreeView 。
所有的标准角色 都是由标准视图使用的默认代表来处理的。这些东西 被理解的方式是在 QItemDelegate 文档中描述的。
一个视图使用的代表是通过 itemDelegate() 函数返回的 。 setItemDelegate() 函数允许你为一个标准视图安装一个自定义的代表 ,而当你为一个自定义的视图设置代表时 ,使用这个函数是必要的。
这里实现的代表使用一个 QSpinBox 来提供编辑设施,并且主要是倾向于用在显示整数的模型中。尽管我们为了这个目的而设置了一个自定义的基于整数的表格模型 ,但是我们也可以简单地使用 QStandardItemModel 来代替 ,因为这个自定义的代表会控制数据条目。我们构造一个表格视图,用来显示模型中的内容 ,而这个视图会使用这个自定义的代表来进行编辑操作。
我们从 QItemDelegate 来子类化这个代表 ,因为我们不想写自定义的显示函数。然而 ,我们还是必须提供用来管理编辑器部件的函数 :
class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
注意在代表构造的时候 ,没有编辑器部件被设置。我们只在需要的时候构造一个编辑器部件 。
在这个示例里 ,当表格视图需要提供一个编辑器时 ,它要求代表来提供一个适合于正在修改的条目的编辑器部件 。视图会向 createEditor() 函数提供所有它需要用来设置一个合适的部件的信息 :
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & /* option */ ,
const QModelIndex & /* index */ ) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
注意 ,我们不需要保存编辑器部件的指针,因为视图会负责在不需要它的时候将它销毁 。
我们将代表的默认事件过滤器安装到编辑器上 ,以确保它提供用户预期的标准编辑快捷 键。可以添加更多的快捷 键到编辑器上,以允许更加复杂的行为;这些是在编辑提示小节描述的 。
视图通过调用我们随后将要定义的函数来确保编辑器的数据和几何属性是 被正确设置的 。 我们可以依据视图提供的模型索引来创建不同的编辑器 。例如 ,如果我们有一列整数和一列字符串 ,我们可以依据当前正在 被编辑的列来返回一个 QSpinBox 或者一个 QLineEdit 。
代表必须提供一个用来将模型数据复制到编辑器中的函数 。在这个示例中 ,我们读取存储在显示角色里的数据,并且据此设置旋转框中的值。
void SpinBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
在这个示例里 ,我们知道编辑器部件是一个旋转 框,但是我们可以为模型中不同种类的数据提供不同的编辑器 ,在那种情况下 ,我们在访问它的成员函数之前,需要先将部件转换成合适的类型。
当用户完成了对旋转 框中的值的修改,视图就通过调用 setModelData() 函数来要求代表将编辑过的值储存到模型中。
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
由于视图为代表管理编辑器部件 ,我们只需要用提供的编辑器中的内容来更新模型 。在这种情况下 ,我们确保旋转 框的信息是最新的,并且使用指定的索引将它包含的 值更新到模型中。
标准的 QItemDelegate 类在完成编辑后会通过发射 closeEditor() 信号来告知视图 。视图确保编辑器部件 被关闭以及销毁。在这个示例里 ,我们只提供简单的编辑设施,所以我们不发射这个信号。
对数据的所有操作 都是通过由 QAbstractItemModel 提供的接口来完成的。这使得代表几乎独立于它所操作的数据的类型,但是仍然需要作一些假设以便使用特定种类的编辑器部件 。在这个示例里 ,我们假设模型一直包含整数值,但是我们仍然可以将这个代表用于不同类型的模型 ,因为 QVariant 为未预知的数据提供有意义的默认 值。
代表负责管理编辑器的几何属性 。当编辑器创建的时候 ,以及条目在视图中的大小或位置发生改变的时候,几何属性必须被设置。幸运的是 ,视图在一个视图选项对象里提供所有必须的几何属性信息 。
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex & /* index */ ) const
{
editor->setGeometry(option.rect);
}
在这个案例中 ,我们只是使用由视图选项提供的条目方框的几何信息 。一个在条目中渲染多个元素的代表不会直接使用条目方框 。它将会参照条目中的其它元素来放置编辑器 。
在编辑之后 ,代表应当向其它组件提供关于编辑过程的结果的提示 ,并且提供能够辅助后续的编辑操作的提示。这是通过带着一个合适的提示发射 closeEditor() 信号来实现的 。这是由我们在构造旋转 框时安装的 QItemDelegate 默认事件过滤器来打理的。
旋转 框的行为可以进行调整,以使它对用户更加友好。在由 QItemDelegate 提供的默认事件过滤器中 ,如果用户敲击 回车 键来确认他/她们在旋转框中的选择,代表提交数据到模型并且关闭旋转 框。我们可以通过安装我们自己的事件过滤器到旋转 框上来改变这个行为,并且提供符合我们的需要的编辑提示;例如 ,我们可以带着 EditNextItem 提示发射 closeEditor() 信号 ,以自动开始编辑视图中的下一个条目。
另一种不需要事件过滤器的实现方法是提供我们自己的编辑器部件 ,比如说子类化 QSpinBox 以提供便利 。这种备选实现方法将让我们更多地控制编辑器部件如何表现 ,代价就是编写附加的代码。通常如果你需要自定义一个标准的Qt 编辑器部件的行为 ,比较简单的方式就是安装一个事件过滤器。
代表不是必须发射这些提示,但是与那些发射提示来支持通用编辑动作的代表相比 , 那些不这么做的将会与程序整合得比较少 ,并且可用性会少一些。
Your opinionsHxLauncher: Launch Android applications by voice commands