简述

上节分享了使用自定义模型QAbstractTableModel来实现复选框。下面我们来介绍另外一种方式:

自定义委托-QAbstractItemDelegate。

效果

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:
case Qt::UserRole:
{
if (nColumn == CHECK_BOX_COLUMN)
{
record.bChecked = value.toBool(); 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::UserRole:
{
if (nColumn == CHECK_BOX_COLUMN)
return record.bChecked;
}
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; return flags;
}

接口说明

  • updateData

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

  • data

    用来显示数据,根据角色(颜色、文本、对齐方式、选中状态等)判断需要显示的内容。

  • setData

    用来设置数据,根据角色(颜色、文本、对齐方式、选中状态等)判断需要设置的内容。

  • headerData

    用来显示水平/垂直表头的数据。

  • flags

    用来设置单元格的标志(可用、可选中、可复选等)。

QStyledItemDelegate

源码

CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{ } CheckBoxDelegate::~CheckBoxDelegate()
{ } // 绘制复选框
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; QStyledItemDelegate::paint(painter, viewOption, index); if (index.column() == CHECK_BOX_COLUMN)
{
bool data = index.model()->data(index, Qt::UserRole).toBool(); QStyleOptionButton checkBoxStyle;
checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;
checkBoxStyle.state |= QStyle::State_Enabled;
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect; QCheckBox checkBox;
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox);
}
} // 响应鼠标事件,更新数据
bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *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()))
{
if (index.column() == CHECK_BOX_COLUMN)
{
bool data = model->data(index, Qt::UserRole).toBool();
model->setData(index, !data, Qt::UserRole);
}
} return QStyledItemDelegate::editorEvent(event, model, option, index);
}

接口说明

  • paint

    用来设置表格样式,绘制复选框-状态、大小、显示区域等。

  • editorEvent

    用来设置数据,响应鼠标事件,判断当前选中状态,互相切换。

样式

复选框样式:

QCheckBox{
spacing: 5px;
color: white;
}
QCheckBox::indicator {
width: 17px;
height: 17px;
}
QCheckBox::indicator:enabled:unchecked {
image: url(:/Images/checkBox);
}
QCheckBox::indicator:enabled:unchecked:hover {
image: url(:/Images/checkBoxHover);
}
QCheckBox::indicator:enabled:unchecked:pressed {
image: url(:/Images/checkBoxPressed);
}
QCheckBox::indicator:enabled:checked {
image: url(:/Images/checkBoxChecked);
}
QCheckBox::indicator:enabled:checked:hover {
image: url(:/Images/checkBoxCheckedHover);
}
QCheckBox::indicator:enabled:checked:pressed {
image: url(:/Images/checkBoxCheckedPressed);
}
QCheckBox::indicator:enabled:indeterminate {
image: url(:/Images/checkBoxIndeterminate);
}
QCheckBox::indicator:enabled:indeterminate:hover {
image: url(:/Images/checkBoxIndeterminateHover);
}
QCheckBox::indicator:enabled:indeterminate:pressed {
image: url(:/Images/checkBoxIndeterminatePressed);
}

使用

QTableView *pTableView = new QTableView(this);
TableModel *pModel = new TableModel(this);
CheckBoxDelegate *pDelegate = new CheckBoxDelegate(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);
pTableView->setItemDelegate(pDelegate); // 加载数据、更新界面
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添加复选框(QAbstractItemDelegate)的更多相关文章

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

    简述 使用QTableView,经常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意以下几点: 三态:不选/半选/全选 自定义风格(样式) 下面我们介绍一下常见的实现方式: 编辑委托. ...

  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. 华为章宇:如何学习开源项目及Ceph的浅析

    转自http://www.csdn.net/article/2014-04-10/2819247-how-to-learn-opensouce-project-&-ceph 摘要:开源技术的学 ...

  2. HTTP请求报文与响应报文

    http://docs.telerik.com/fiddler/KnowledgeBase/HTTP HTTP请求报文与响应报文 HTTP http://www.w3.org/Protocols/rf ...

  3. Unity3D 与 objective-c 之间数据交互。iOS SDK接口封装Unity3D接口

    原地址:http://www.cnblogs.com/qingjoin/p/3638915.html Unity 3D 简单工程的创建.与Xcode 导出到iOS 平台请看这 Unity3D 学习 创 ...

  4. Winform 窗体的操作

    原文:http://www.cnblogs.com/Billy-rao/archive/2012/05/16/2503437.html 怎样能使winform窗体的大小固定住,不能调整其大小 窗体Fo ...

  5. POJ 1734

    #include<iostream> #include<stdio.h> #define MAXN 105 #define inf 123456789 using namesp ...

  6. 文件夹和文件、Path类、流、序列化

    循环访问目录树 参考: http://msdn.microsoft.com/zh-cn/library/bb513869.aspx 循环访问目录树”的意思是在指定的根文件夹下,访问每个嵌套子目录中任意 ...

  7. Elasticsearch 学习~

    http://cloud.51cto.com/art/201505/476322.htmEs https://www.gitbook.com/book/asdgh000/mongodb-elastic ...

  8. Python分析NGINX LOG版本二

    不好意思,上一版逻辑有错误,(只分析了一次就没了) 此版改正. 按同事要改,作成传参数形式,搞定. #!/usr/bin/env python # coding: utf-8 ############ ...

  9. Android 使用MediaRecorder录音

    package com.example.HyyRecord; import android.app.Activity; import android.content.Intent; import an ...

  10. 通过快捷键及cmd命令注销系统

    公司的外网内网是隔离的 外网的远程电脑屏幕一半卡那了,页面注销键正好在卡死的那一半屏幕上,用以下简单方法注销远程重新连接,问题解决了. 1.通过快捷键win+r打开“运行...” 2.输入CMD 回车 ...