Qt之QTableView添加复选框(QAbstractTableModel)

简介: 简述使用QTableView,经常会遇到复选框,要实现一个好的复选框,除了常规的功能外,还应注意以下几点:三态:不选/半选/全选自定义风格(样式)下面我们介绍一下常见的实现方式:编辑委托。 方式:利用委托重载createEditor(),激活QCheckBox。 特点:必须双击/选中,才能显示CheckBox控件。一般不满足实际中的直接显示的需要。

简述

使用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);
目录
相关文章
|
6月前
|
C++
[Qt5&控件] 复选框QCheckBox的使用
[Qt5&控件] 复选框QCheckBox的使用
184 0
|
索引
Qt之QTableView添加复选框(QAbstractItemDelegate)
简述 上节分享了使用自定义模型QAbstractTableModel来实现复选框。下面我们来介绍另外一种方式: 自定义委托-QAbstractItemDelegate。 简述 效果 QAbstractTableModel 源码 接口说明 QStyledItemDelegate 源码 接口说明 样式 使用 效果 QAbstrac
1834 0
|
4月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
181 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
3月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
89 0
|
2月前
|
开发工具 C++
qt开发技巧与三个问题点
本文介绍了三个Qt开发中的常见问题及其解决方法,并提供了一些实用的开发技巧。
|
2月前
|
3月前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
158 2
下一篇
无影云桌面