方法一:设置QAbstractTableModel的flags()函数来实现。特点:直接显示,可定义样式,默认左对齐,很难实现居中、右对齐。
方法二:自定义委托QAbstractItemDelegate,通过paint()函数来实现。特点:这种方式比较复杂,但适合扩展,除了可以嵌入复选框,还可以绘制其它控件-按钮、图片等,定义样式无效。
1、继承QAbstractTableModel类,实现MyTableModel类。
#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H#include <QAbstractTableModel>/*** @brief 表格展示的一行的数据结构*/
struct FileRecord
{bool bChecked;QString strFilePath;
};/*** @brief 自定义TableModel,用于展示接口的使用* @details* 继承QAbstractTableModel需要实现至少三个接口:* rowCount、columnCount、data*/
class MyTableModel : public QAbstractTableModel
{Q_OBJECT
public:explicit MyTableModel(QObject *parent = nullptr);//更新数据void updateData(QList<FileRecord> recordList);//获取行数int rowCount(const QModelIndex &parent = QModelIndex()) const override;//获取列数int columnCount(const QModelIndex &parent = QModelIndex()) const override;//获取单元格数据QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;//设置单元格数据bool setData(const QModelIndex &index, const QVariant &value,int role = Qt::EditRole) override;//单元格的可操作性标志位,如可编辑,可选中等Qt::ItemFlags flags(const QModelIndex& index) const override;private://数据QList<FileRecord> m_recordList;
};
#endif // MYTABLEMODEL_H
#define CHECK_BOX_COLUMN 0 //复选框
#define FILE_PATH_COLUMN 1 //文件路径MyTableModel::MyTableModel(QObject *parent): QAbstractTableModel(parent)
{}MyTableModel::~MyTableModel()
{}// 更新表格数据
void MyTableModel::updateData(QList<FileRecord> recordList)
{beginResetModel();m_recordList = recordList;endResetModel();
}// 行数
int MyTableModel::rowCount(const QModelIndex &parent) const
{return unt();
}// 列数
int MyTableModel::columnCount(const QModelIndex &parent) const
{return 2;
}// 设置表格项数据
bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{if (!index.isValid())return false;int nColumn = lumn();FileRecord record = m_recordList.w());switch (role){case Qt::DisplayRole:{if (nColumn == FILE_PATH_COLUMN){record.strFilePath = String();w(), record);emit dataChanged(index, index);return true;}}case Qt::CheckStateRole:{if (nColumn == CHECK_BOX_COLUMN){record.bChecked = (Int() == Qt::Checked);w(), record);emit dataChanged(index, index);//这里可以添加checkbox联动事件,emit到上层界面去处理。return true;}}default:return false;}return false;
}// 表格项数据
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{if (!index.isValid())return QVariant();int nRow = w();int nColumn = lumn();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 MyTableModel::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::MyTableModel TableModel::flags(const QModelIndex &index) const
{if (!index.isValid())return QAbstractItemModel::flags(index);Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;if (lumn() == CHECK_BOX_COLUMN)flags |= Qt::ItemIsUserCheckable;return flags;
}
2、设置样式。
QTableView
{ color: white;gridline-color: white; /*表格内框颜色*/ background-color: rgb(27, 27, 27); /*表格内背景色*/ alternate-background-color: rgb(64, 64, 64); selection-color: white; /*选中区域的文字颜色*/ selection-background-color: rgb(77, 77, 77); /*选中区域的背景色*/ border: 1px white; /*边框像素和颜色*/ border-radius: 0px; /*边框圆角半径*/ padding: 1px 1px; outline:0px; /*去除选中时的虚线框*/
}
QTableView::item {color: #5F5F5F;text-align: center;padding-left: 6px;padding-right: 6px;
}/* 左上角的空白区域样式 */
QTableView QTableCornerButton::section
{ color: white; background-color: skyblue;border: 1px solid white; border-radius:0px; border-color: rgb(64, 64, 64);
}/* 表头样式 */
QTableView QHeaderView {background: transparent;
}
QTableView QHeaderView::section {color: #8C8C8C;background-color: white;border-bottom: 1px solid #CED4DA;border-top: none;border-left: none;border-right: 1px solid #CED4DA;text-align: center;font-weight: bold;min-width: 30;min-height: 30;
}QTableView::item{
border:0;}/* 表格中复选框样式 */
QTableView::indicator {width: 20px;height: 20px;
}QTableView::indicator:unchecked{image:url(:/SwitchOff.png);}
QTableView::indicator:checked{image:url(:/SwitchOn.png);}
3、使用
QTableView *pTableView = new QTableView(this);
MyTableModel *pModel = new MyTableModel(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("D:/image%1.png").arg(i + 1);recordList.append(record);
}
pModel->updateData(recordList);
QTableView如果实现指定项不可编辑状态方法:
1)重写Model的虚函数flags,指定index下的item的flags去除Qt::ItemIsEditable标志。
2)重写Delegate的createEditor,实现返回空的editor即可。
1、CheckBoxDelegate委托类。
ifndef CHECKBOXDELETAGE_H
#define CHECKBOXDELETAGE_H#include <QStyledItemDelegate>class QPixmap;
class CheckBoxDelegate : public QStyledItemDelegate
{Q_OBJECTpublic:enum class CheckBoxPaintType : quint8{SysControl = 0, // 系统控件OwnerDraw = 1, // 自绘CheckBoxDrawImage = 2, // 绘制图片};public:explicit CheckBoxDelegate(CheckBoxPaintType type = CheckBoxPaintType::SysControl, QWidget *parent = nullptr);~CheckBoxDelegate();void initCheckBoxPixmaps(CheckBoxPaintType type);void initCheckBoxPixmapBySysControl(const QString& key, bool checked);void initCheckBoxPixmapByOwnerDraw(const QString& key, bool checked);void initCheckBoxPixmapByDrawImage(const QString& key, bool checked);// 虚函数void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;signals:private:QPixmap* mCheckedPix = nullptr;QPixmap* mUnCheckedPix = nullptr;
};#endif // CHECKBOXDELETAGE_H
#include "checkboxdeletage.h"
#include <QCheckBox>
#include <QApplication>
#include <QMouseEvent>
#include <QPixmapCache>
#include <QPainter>CheckBoxDelegate::CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType type, QWidget *parent): QStyledItemDelegate(parent)
{initCheckBoxPixmaps(type);
}CheckBoxDelegate::~CheckBoxDelegate()
{delete mCheckedPix;delete mUnCheckedPix;
}void CheckBoxDelegate::initCheckBoxPixmaps(CheckBoxDelegate::CheckBoxPaintType type)
{switch (type){case CheckBoxPaintType::SysControl:initCheckBoxPixmapBySysControl("checked", true);initCheckBoxPixmapBySysControl("unchecked", false);break;case CheckBoxPaintType::OwnerDraw:initCheckBoxPixmapByOwnerDraw("checked", true);initCheckBoxPixmapByOwnerDraw("unchecked", false);break;case CheckBoxPaintType::DrawImage:initCheckBoxPixmapByDrawImage("checked", true);initCheckBoxPixmapByDrawImage("unchecked", false);break;default:break;}
}void CheckBoxDelegate::initCheckBoxPixmapBySysControl(const QString &key, bool checked)
{QPixmap* pix = new QPixmap(13,13);QPainter painter(pix);QStyleOptionToolButton style;style.iconSize = QSize(13, 13);style.state = checked ? QStyle::State_On : QStyle::State_Off;style.state |= QStyle::State_ = QRect(0,0, 13,13);QCheckBox box;QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &style, &painter, &box);if (checked)mCheckedPix = pix;elsemUnCheckedPix = pix;
}void CheckBoxDelegate::initCheckBoxPixmapByOwnerDraw(const QString &key, bool checked)
{QPixmap* pix = new QPixmap(13,13);QPainter painter(pix);painter.setPen(QColorConstants::Green);QRect rect(0,0,13,13);// 抗锯齿painter.setRenderHint(QPainter::Antialiasing);painter.setBrush(QBrush(QColorConstants::White));painter.drawRect(rect);if (checked){QPointF points[3] = {QPointF(rect.x() + rect.width() * 2 / 11, rect.y() + rect.height() * 6 / 11),QPointF(rect.x() + rect.width() * 4 / 11, rect.y() + rect.height() * 8 / 11),QPointF(rect.x() + rect.width() * 9 / 11, rect.y() + rect.height() * 3 / 11),};painter.setPen(QPen(QBrush(QColorConstants::Green),2));painter.drawPolyline(points, 3);}if (checked)mCheckedPix = pix;elsemUnCheckedPix = pix;
}void CheckBoxDelegate::initCheckBoxPixmapByDrawImage(const QString &key, bool checked)
{QPixmap* pix = new QPixmap(checked ? ":/image/checked.png" : ":/image/unchecked.png");if (checked)mCheckedPix = pix;elsemUnCheckedPix = pix;
}void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QStyleOptionViewItem viewOption(option);initStyleOption(&viewOption, index);if (stFlag(QStyle::State_HasFocus))viewOption.state ^= QStyle::State_HasFocus;QStyledItemDelegate::paint(painter, option, index);bool checked = index.data(Qt::UserRole).toBool();QPixmap* pix = checked? mCheckedPix : mUnCheckedPix;if (pix){// 居中显示QRect rect = pix->rect();int offsetX = width() / 2 - rect.width() / 2;int offsetY = height() / 2 - rect.height() / () + offsetX, () + offsetY);painter->drawPixmap(rect, *pix);}
}bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick){// 鼠标单双击切换选中状态QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);if (ains(mouseEvent->pos())){model->setData(index, !model->data(index, Qt::UserRole).toBool(), Qt::UserRole);}}return QStyledItemDelegate::editorEvent(event, model, option, index);
}
2、继承QAbstractTableModel类,实现MyTableModel类。
#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H#include <QAbstractTableModel>/*** @brief 表格展示的一行的数据结构*/
struct FileRecord
{bool bChecked;QString strFilePath;
};/*** @brief 自定义TableModel,用于展示接口的使用* @details* 继承QAbstractTableModel需要实现至少三个接口:* rowCount、columnCount、data*/
class MyTableModel : public QAbstractTableModel
{Q_OBJECT
public:explicit MyTableModel(QObject *parent = nullptr);//更新数据void updateData(QList<FileRecord> recordList);//获取行数int rowCount(const QModelIndex &parent = QModelIndex()) const override;//获取列数int columnCount(const QModelIndex &parent = QModelIndex()) const override;//获取单元格数据QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;//设置单元格数据bool setData(const QModelIndex &index, const QVariant &value,int role = Qt::EditRole) override;//单元格的可操作性标志位,如可编辑,可选中等Qt::ItemFlags flags(const QModelIndex& index) const override;private://数据QList<FileRecord> m_recordList;
};
#endif // MYTABLEMODEL_H
#define CHECK_BOX_COLUMN 0 //复选框
#define FILE_PATH_COLUMN 1 //文件路径MyTableModel::MyTableModel(QObject *parent): QAbstractTableModel(parent)
{}MyTableModel::~MyTableModel()
{}// 更新表格数据
void MyTableModel::updateData(QList<FileRecord> recordList)
{beginResetModel();m_recordList = recordList;endResetModel();
}// 行数
int MyTableModel::rowCount(const QModelIndex &parent) const
{return unt();
}// 列数
int MyTableModel::columnCount(const QModelIndex &parent) const
{return 2;
}// 设置表格项数据
bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{if (!index.isValid())return false;int nColumn = lumn();FileRecord record = m_recordList.w());switch (role){case Qt::DisplayRole:{if (nColumn == FILE_PATH_COLUMN){record.strFilePath = String();w(), record);emit dataChanged(index, index);return true;}}case Qt::CheckStateRole:case Qt::UserRole:{if (nColumn == CHECK_BOX_COLUMN){record.bChecked = (Int() == Qt::Checked);w(), record);emit dataChanged(index, index);return true;}}default:return false;}return false;
}// 表格项数据
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{if (!index.isValid())return QVariant();int nRow = w();int nColumn = lumn();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:case Qt::UserRole:{if (nColumn == CHECK_BOX_COLUMN)return record.bChecked ? Qt::Checked : Qt::Unchecked;}default:return QVariant();}return QVariant();
}// 表头数据
QVariant MyTableModel::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::MyTableModel TableModel::flags(const QModelIndex &index) const
{if (!index.isValid())return QAbstractItemModel::flags(index);Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;if (lumn() == CHECK_BOX_COLUMN)flags |= Qt::ItemIsUserCheckable;return flags;
}
3、使用
QTableView *pTableView = new QTableView(this);
MyTableModel *pModel = new MyTableModel(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->setItemDelegateForColumn(0, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::SysControl, this));
//pTableView->setItemDelegateForColumn(0, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::OwnerDraw, this));
//pTableView->setItemDelegateForColumn(0, new CheckBoxDelegate(CheckBoxDelegate::CheckBoxPaintType::DrawImage, this));
// 不可编辑
pTableView->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
// 整行选中
pTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
// 多行可选
pTableView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
pTableView->setModel(pModel);// 加载数据、更新界面
QList<FileRecord> recordList;
for (int i = 0; i < 5; ++i)
{FileRecord record;record.bChecked = false;record.strFilePath = QString("D:/image%1.png").arg(i + 1);recordList.append(record);
}
pModel->updateData(recordList);
本文发布于:2024-02-01 01:48:56,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170672333732982.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |