简述

使用QTableView,经常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意以下几点:

  1. 三态:不选/半选/全选
  2. 自定义风格(样式)

下面我们介绍一下常见的实现方式:

  • 编辑委托。

    方式:利用委托重载createEditor(),激活QCheckBox。

    特点:必须双击/选中,才能显示CheckBox控件。一般不满足实际中的直接显示的需要。

  • 使用QTableView的setIndexWidget(const QModelIndex &index, QWidget *widget)来实现。

    此功能用来显示可视区域内对应一个数据项的静态内容。如果想显示自定义的动态内容或执行自定义编辑器部件,子类化QItemDelegate代替。也就是说,这只适合做静态数据的显示,不适合做一些插入、更新、删除操作的数据显示。

  • 自定义模型QAbstractTableModel,通过flags()函数来实现。

    方式:通过将flags()设置为Qt::ItemIsUserCheckable实现可选中,然后配合setData()与data()来实现。

    特点:直接显示,可定义样式,默认左对齐,很难实现居中、右对齐。

  • 自定义委托QAbstractItemDelegate,通过paint()函数来实现。

    方式:通过控制editorEvent()实现鼠标的点击进行全选/半选/不选,然后由paint()实时绘制。

    特点:这种方式比较复杂,但适合扩展,除了可以嵌入复选框,还可以绘制其它控件-按钮、图片等。

效果

下面我们来介绍如何利用QAbstractTableModel的flags()函数来实现复选功能。

QAbstractTableModel

源码

table_model.cpp

#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

    主要用于更新数据,刷新界面。

  • 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);

Qt之QTableView添加复选框(QAbstractTableModel)的更多相关文章

  1. Qt之QTableView添加复选框(QAbstractItemDelegate)

    简述 上节分享了使用自定义模型QAbstractTableModel来实现复选框.下面我们来介绍另外一种方式: 自定义委托-QAbstractItemDelegate. 简述 效果 QAbstract ...

  2. Qt之QHeaderView添加复选框

    简述 前面分享了QTableView中如何添加复选框.本节主要介绍QTableView中的表头-QHeaderView添加复选框的功能,下面以水平表头为例,垂直表头类似! 简述 效果 QHeaderV ...

  3. PyQt5之 QTableView 添加复选框(自定义委托)

    import sys from untitled import Ui_Form from PyQt5.QtWidgets import QApplication, QWidget, QStyleOpt ...

  4. Qt之QHeaderView加入复选框

    简述 前面分享了QTableView中怎样加入复选框. 本节主要介绍QTableView中的表头-QHeaderView加入复选框的功能,以下以水平表头为例.垂直表头相似! 简述 效果 QHeader ...

  5. 组合框里添加复选框的方法(使用勾选的假象,用图片代替而已,并非QT原生支持)

    组合框可以看作是列表框和文本框的组合,因其占据的空间少,使用操作方便,常被界面设计人员用于界面开发设计中,在有限个输入的条件下,组合框常用来代替文本框,这样从用户使用角度来看,更趋人性化,所见即所得. ...

  6. QListWidget的QComboBox下拉列表添加复选框及消息处理

    要在QComboBox下拉列表项中添加复选框,并进行消息处理,在网上搜索了很久没有找到太多有用的信息和实际的例子,但从中还是找到了一些提示性的资料,根据这些简短的介绍,最终实现了这个功能. QComb ...

  7. 雷林鹏分享:jQuery EasyUI 数据网格 - 添加复选框

    jQuery EasyUI 数据网格 - 添加复选框 本实例演示如何放置一个复选框列到数据网格(DataGrid).通过复选框,用户将可以选择 选中/取消选中 网格行数据. 为了添加一个复选框列,我们 ...

  8. dojo:为数据表格添加复选框

    一.添加复选框 此时应该选用EnhancedGrid,而不是普通的DataGrid.添加复选框需要设置EnhancedGrid的plugins属性,如下: gridLayout =[{ default ...

  9. DateGridView标题列头添加复选框

    第一:添加列标题时,添加两个空格——用于显示复选框: 第二:实现列标题添加复选框,代码如下: private void AddCheckeBoxToDGVHeader(DataGridView dgv ...

随机推荐

  1. easyui页面布局

    html: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  2. asp.net 中给gridview添加自动序号

    第一种方式,直接在Aspx页面GridView模板列中.这种的缺点是到第二页分页时又重新开始了. 代码如下: <asp:TemplateField HeaderText="序号&quo ...

  3. vs2008中使用正则删除空行

    起因 今天下了段代码复制到VS2008中想好好学习下,结果发现每隔一行都有一行空白行(如下图),如果只有几行么手动删下就好了,但是这边估计有几百行,我也不知道VS2008有没有什么支持快速删除空白行的 ...

  4. hihocoder #1301 : 筑地市场 数位dp+二分

    题目链接: http://hihocoder.com/problemset/problem/1301?sid=804672 题解: 二分答案,每次判断用数位dp做. #include<iostr ...

  5. DevExpress控件使用系列--ASPxTreeList

      控件功能 结合列表控件及树控件的优点,在列表控件中实现类型树的多层级操作 官方说明 http://documentation.devexpress.com/#AspNet/clsDevExpres ...

  6. 【BZOJ】【3404】【USACO2009 Open】Cow Digit Game又见数字游戏

    博弈论 Orz ZYF 从前往后递推……反正最大才10^6,完全可以暴力预处理每个数的状态是必胜还是必败(反正才两个后继状态),然后O(1)查询……我是SB /******************** ...

  7. [转载]MongoDB 标准连接字符串

    MongoDB 标准连接字符串 mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[data ...

  8. Oracle中的 UPDATE FROM 解决方法

    转:http://www.cnblogs.com/JasonLiao/archive/2009/12/23/1630895.html Oracle中的 UPDATE FROM 解决方法 在表的更新操作 ...

  9. EF提供的三种查询方式

    這邊簡單介紹一下,ADO.Net Entity Framework 提供的三種查詢方式, Linq to Entities Query Builder Mothed Entity SQL Langua ...

  10. 李洪强iOS开发之【零基础学习iOS开发【01-前言】03-前景和难易度分析

    一.iOS开发的前景 2012年3月份,苹果公司的市值已经突破5000亿美元,成为世界上市值最大的公司.5000亿是神马概念呢? 可以帮助陷入欧债危机的8个国家偿还债务 可以买下35个天安门广场.34 ...