一文总结Qt表格项目的代理类"/>
【Qt】一文总结Qt表格项目的代理类
一、开篇
软件设计中,表格是一种常用的数据呈现控件,然而在实际的项目中,会出现对表格中的单行数据操作的情况:例如可能会编辑表格、删除表格数据等。这两个操作方式在设计中,可能会同时放在数据表格的行当中。例如如下图所示的效果:
在上图中,左侧是一列选择框、最右侧的每一个表格单元中都放置了两个按钮,表示对该行数据的操作。
本文,将描述在Qt中,如何使用Qt提供的表格代理类来实现这种功能。
效果走一波:
(注)本文只描述左侧选择框代理类的实现。
首先来看看Qt提供的代码类。在开发中,常使用QItemDelegate
、QStyledItemDelegate
代理类。
(1)QItemDelegate:该类为表格模型中的数据项提供显示和编辑工具。
(2)QStyledItemDelegate:该类与QItemDelegate代理类功能大同小异,但是QStyledItemDelegate接管了绘制Qt项视图的工作。所有我们在创建新代理时建议使用QStyledItemDelegate。
带自定义我们的代理类使,需要重载createEditor()
、paint()
两个虚函数:
(1)createEditor
函数原型如下:
QWidget *QStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) cons
该函数将返回用于编辑由索引指定的条目的小部件。parent部件和option样式选项用于控制编辑器部件的显示方式。
(2)paint
函数原型如下:
void QStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
该函数使用index指定的item项的给定painter和option样式选项呈现代理类。
二、一个示例
本文以选择框代理类为例。
为了实现我们自己的选择框代理类,我们需要将QStyledItemDelegate
作为父类,并重载paint()
、editorEvent()
,在该类中可以放置自己类的私有数据:
class checkBoxDelegate : public QStyledItemDelegate
{Q_OBJECT
public:checkBoxDelegate(int checkBoxWidth,int checkBoxHeight,QObject *parent = nullptr):QStyledItemDelegate(parent),m_checkBoxWidth(checkBoxWidth),m_checkBoxHeight(checkBoxHeight){}~checkBoxDelegate()override{}void paint(QPainter* painter, const QStyleOptionViewItem & option,const QModelIndex &index) const override;bool editorEvent(QEvent *event, QAbstractItemModel *m_model,const QStyleOptionViewItem &option,const QModelIndex &index) override;int m_checkBoxWidth,m_checkBoxHeight;
};
然后实现paint
、editorEvent
两个函数,如下代码:
void checkBoxDelegate::paint
(QPainter* painter,const QStyleOptionViewItem & option,const QModelIndex &index
) const
{QStyleOptionViewItem viewOption(option);initStyleOption(&viewOption, index);if (option.state.testFlag(QStyle::State_HasFocus))viewOption.state = viewOption.state ^ QStyle::State_HasFocus;painter->setRenderHint(QPainter::Antialiasing,true);QStyledItemDelegate::paint(painter, viewOption, index);bool data = index.model()->data(index, Qt::UserRole).toBool();int nHalf = (option.rect.width() - m_checkBoxWidth)/2;int nTop = (option.rect.height() - m_checkBoxHeight)/2;QStyleOptionButton checkBoxOptionStyle;checkBoxOptionStyle.state = data ? QStyle::State_On : QStyle::State_Off;checkBoxOptionStyle.state |= QStyle::State_Enabled;checkBoxOptionStyle.iconSize = QSize(12, 12);checkBoxOptionStyle.rect = QRect(option.rect.left() + nHalf ,option.rect.top() + nTop, m_checkBoxWidth, m_checkBoxHeight);QCheckBox checkBox;QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxOptionStyle, painter, &checkBox);
}bool checkBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *m_model,const QStyleOptionViewItem &option,const QModelIndex &index)
{QRect decorationRect = option.rect;QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())){bool data = m_model->data(index, Qt::UserRole).toBool();m_model->setData(index,!data, Qt::UserRole);}return true;
}
对于代理类中还有更多可以重载的虚函数:
在开发中,可以根据实际情况来重新重载和实现,具体功能可参见官方文档(.html#paint)
三、代理类的使用
当我们设计到代理类后,可以在表格中使用了。使用setItemDelegateForColumn()
为表格设置代理:
m_tableView->setItemDelegateForColumn(0,new checkBoxDelegate(20,20,this));
本文完!
搜索/关注【嵌入式小生】微信公众号。回复2077即可获取本文源码工程。
更多推荐
【Qt】一文总结Qt表格项目的代理类
发布评论