使用QTableView,常常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意如下几点:app
下面咱们介绍一下常见的实现方式:编辑器
编辑委托。
方式:利用委托重载createEditor(),激活QCheckBox。
特色:必须双击/选中,才能显示CheckBox控件。通常不知足实际中的直接显示的须要。函数
使用QTableView的setIndexWidget(const QModelIndex &index, QWidget *widget)来实现。
此功能用来显示可视区域内对应一个数据项的静态内容。若是想显示自定义的动态内容或执行自定义编辑器部件,子类化QItemDelegate代替。也就是说,这只适合作静态数据的显示,不适合作一些插入、更新、删除操做的数据显示。this
自定义模型QAbstractTableModel,经过flags()函数来实现。
方式:经过将flags()设置为Qt::ItemIsUserCheckable实现可选中,而后配合setData()与data()来实现。
特色:直接显示,可定义样式,默认左对齐,很难实现居中、右对齐。url
自定义委托QAbstractItemDelegate,经过paint()函数来实现。
方式:经过控制editorEvent()实现鼠标的点击进行全选/半选/不选,而后由paint()实时绘制。
特色:这种方式比较复杂,但适合扩展,除了能够嵌入复选框,还能够绘制其它控件-按钮、图片等。spa
下面咱们来介绍如何利用QAbstractTableModel的flags()函数来实现复选功能。.net
table_model.cppcode
#define CHECK_BOX_COLUMN 0 #define File_PATH_COLUMN 1 TableModel::TableModel(QObject *parent) : QAbstractTableModel(parent) { } TableModel::~TableModel() { } // 更新表格数据 void TableModel::updateData(QList<FileRecord> recordList) { m_recordList = recordList; beginResetModel(); endResetModel(); } // 行数 int TableModel::rowCount(const QModelIndex &parent) const { return m_recordList.count(); } // 列数 int TableModel::columnCount(const QModelIndex &parent) const { return 2; } // 设置表格项数据 bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) return false; int nColumn = index.column(); FileRecord record = m_recordList.at(index.row()); switch (role) { case Qt::DisplayRole: { if (nColumn == File_PATH_COLUMN) { record.strFilePath = value.toString(); m_recordList.replace(index.row(), record); emit dataChanged(index, index); return true; } } case Qt::CheckStateRole: { if (nColumn == CHECK_BOX_COLUMN) { record.bChecked = (value.toInt() == Qt::Checked); m_recordList.replace(index.row(), record); emit dataChanged(index, index); return true; } } default: return false; } return false; } // 表格项数据 QVariant TableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); int nRow = index.row(); int nColumn = index.column(); FileRecord record = m_recordList.at(nRow); switch (role) { case Qt::TextColorRole: return QColor(Qt::white); case Qt::TextAlignmentRole: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); case Qt::DisplayRole: { if (nColumn == File_PATH_COLUMN) return record.strFilePath; return ""; } case Qt::CheckStateRole: { if (nColumn == CHECK_BOX_COLUMN) return record.bChecked ? Qt::Checked : Qt::Unchecked; } default: return QVariant(); } return QVariant(); } // 表头数据 QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const { switch (role) { case Qt::TextAlignmentRole: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); case Qt::DisplayRole: { if (orientation == Qt::Horizontal) { if (section == CHECK_BOX_COLUMN) return QStringLiteral("状态"); if (section == File_PATH_COLUMN) return QStringLiteral("文件路径"); } } default: return QVariant(); } return QVariant(); } // 表格可选中、可复选 Qt::ItemFlags TableModel::flags(const QModelIndex &index) const { if (!index.isValid()) return QAbstractItemModel::flags(index); Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() == CHECK_BOX_COLUMN) flags |= Qt::ItemIsUserCheckable; return flags; }
updateData
主要用于更新数据,刷新界面。blog
data
用来显示数据,根据角色(颜色、文本、对齐方式、选中状态等)判断须要显示的内容。接口
setData
用来设置数据,根据角色(颜色、文本、对齐方式、选中状态等)判断须要设置的内容。
headerData
用来显示水平/垂直表头的数据。
flags
用来设置单元格的标志(可用、可选中、可复选等)。
QSS不只能够设置表格、表格项样式(背景、文本等),也能够经过indicator来设置复选框的样式:
QTableView { border: 1px solid rgb(50, 50, 50); background: rgb(57, 58, 60); gridline-color: rgb(60, 60, 60); } QTableView::item { border: none; border-bottom: 1px solid rgb(50, 50, 50); } QTableView::item:selected { background: rgb(0, 160, 230); } QTableView::indicator { width: 17px; height: 17px; } QTableView::indicator:enabled:unchecked { image: url(:/Images/checkBox); } QTableView::indicator:enabled:unchecked:hover { image: url(:/Images/checkBoxHover); } QTableView::indicator:enabled:unchecked:pressed { image: url(:/Images/checkBoxPressed); } QTableView::indicator:enabled:checked { image: url(:/Images/checkBoxChecked); } QTableView::indicator:enabled:checked:hover { image: url(:/Images/checkBoxCheckedHover); } QTableView::indicator:enabled:checked:pressed { image: url(:/Images/checkBoxCheckedPressed); } QTableView::indicator:enabled:indeterminate { image: url(:/Images/checkBoxIndeterminate); } QTableView::indicator:enabled:indeterminate:hover { image: url(:/Images/checkBoxIndeterminateHover); } QTableView::indicator:enabled:indeterminate:pressed { image: url(:/Images/checkBoxIndeterminatePressed); }
QTableView *pTableView = new QTableView(this); TableModel *pModel = new TableModel(this); // 设置单行选中、最后一列拉伸、表头不高亮、无边框等 pTableView->setSelectionBehavior(QAbstractItemView::SelectRows); pTableView->horizontalHeader()->setStretchLastSection(true); pTableView->horizontalHeader()->setHighlightSections(false); pTableView->verticalHeader()->setVisible(false); pTableView->setShowGrid(false); pTableView->setFrameShape(QFrame::NoFrame); pTableView->setSelectionMode(QAbstractItemView::SingleSelection); pTableView->setModel(pModel); // 加载数据、更新界面 QList<FileRecord> recordList; for (int i = 0; i < 5; ++i) { FileRecord record; record.bChecked = false; record.strFilePath = QString("E:/Qt/image_%1.png").arg(i + 1); recordList.append(record); } pModel->updateData(recordList);