#include "tableviewex.h" #include #include #include TableViewEx::TableViewEx(QWidget *parent) : QTableView(parent) { //设置model setModel(&m_model); //设置所有单元格不可编辑(注意: 设计器里不能设置, 否则这里的设置不生效, 因为在setupUi里先执行了构造函数再执行设置方法) setEditTriggers(QAbstractItemView::NoEditTriggers); //设置右键菜单模式(注意: 设计器里不能设置, 否则这里的设置不生效, 因为在setupUi里先执行了构造函数再执行设置方法) setContextMenuPolicy(Qt::CustomContextMenu); //禁用滚动条右键菜单 verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu); horizontalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu); //冻结横向滚动条, 否则点击未完全显示的单元格时, 表格会自动滚动来让单元格完全显示 // setHorizontalScrollBar(new FrozenScrollBar(this)); //选中时选中一行 setSelectionBehavior(QAbstractItemView::SelectRows); //SetDragEnable(false); } void TableViewEx::ClearModel() { m_model.clear(); SetHeaders(); //m_model.ClearHTMLContent(); } bool TableViewEx::RemoveRow(int row) { bool isSelected = (currentIndex().row() == row); //这里使用model()来删除, 如果使用了代理model, 删除代理model的时候, 源model的行也会被删除 model()->removeRow(row); if(isSelected && model()->rowCount() != 0) { SetCurrentRow(0); } if(m_verticalScrollBar != nullptr) { QModelIndex topLeft = model()->index(row, 0); QModelIndex bottomRight = model()->index(row, model()->columnCount() - 1); emit model()->dataChanged(topLeft, bottomRight); } return true; } bool TableViewEx::RemoveRow(const QModelIndex &index) { return RemoveRow(index.row()); } bool TableViewEx::IsEmpty(bool forSourceModel) { QAbstractItemModel *pModel = GetModel(forSourceModel); return (pModel->rowCount() == 0); } void TableViewEx::SetCurrentRow(int row) { /*---------------------------------------------------------------- * 这里必须要使用model()->index(..)来获取index, 因为model()取到的才是实际的model * 假如这个tableview使用了代理model, 则model()是代理的model, 而m_model则是源model ----------------------------------------------------------------*/ setCurrentIndex(model()->index(row, 0)); } QAbstractItemModel *TableViewEx::GetModel(bool sourceModel) { return sourceModel?(&m_model):model(); } void TableViewEx::OnScrollBarDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) { Q_UNUSED(topLeft); Q_UNUSED(bottomRight); Q_UNUSED(roles); if(m_verticalScrollBar != nullptr) { //获取视图的大小 QSize viewportSize = viewport()->size(); //获取总行数 int nRowCount = model()->rowCount(); int nTotalRowHeight = 0; //计算总行高 for(int row = 0; row < nRowCount; ++row) { nTotalRowHeight += rowHeight(row); } //判断是否需要显示滚动条 bool bNeedScrollBar = nTotalRowHeight > viewportSize.height(); QTimer::singleShot(0, this, [=]() { if(bNeedScrollBar) { //判断表头是否显示 if(horizontalHeader()->isVisible()) { //在布局完成后设置垂直滚动条范围 m_verticalScrollBar->resize(QSize(6, height() - 48)); m_verticalScrollBar->move(width() - 6, 48); m_verticalScrollBar->setRange(this->verticalScrollBar()->minimum(), this->verticalScrollBar()->maximum()); m_verticalScrollBar->show(); } else { //在布局完成后设置垂直滚动条范围 m_verticalScrollBar->resize(QSize(6, height())); m_verticalScrollBar->move(width() - 6, 0); m_verticalScrollBar->setRange(this->verticalScrollBar()->minimum(), this->verticalScrollBar()->maximum()); m_verticalScrollBar->show(); } } else { m_verticalScrollBar->hide(); } }); } if(m_horizontalScrollBar != nullptr) { //获取视图的大小 QSize viewportSize = viewport()->size(); //获取总列数 int nColCount = model()->columnCount(); QTimer::singleShot(0, this, [=]() { int nTotalColWidth = 0; //计算总列宽 for(int col = 0; col < nColCount; ++col) { nTotalColWidth += columnWidth(col); } //判断是否需要显示滚动条 bool bNeedScrollBar = nTotalColWidth > viewportSize.width(); if(bNeedScrollBar) { //在布局完成后设置横向滚动条范围 m_horizontalScrollBar->resize(QSize(width(), 6)); m_horizontalScrollBar->move(0, height() - 6); m_horizontalScrollBar->setRange(this->horizontalScrollBar()->minimum(), this->horizontalScrollBar()->maximum()); m_horizontalScrollBar->show(); } else { m_horizontalScrollBar->hide(); } }); } } void TableViewEx::OnModelReset() { if(m_verticalScrollBar) { m_verticalScrollBar->hide(); } if(m_horizontalScrollBar) { m_horizontalScrollBar->hide(); } } void TableViewEx::SetVerticalScrollBar(bool bIsNeed) { if(bIsNeed && m_verticalScrollBar == nullptr) { setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //自定义滚动条 m_verticalScrollBar = new QScrollBar(Qt::Orientation::Vertical, this); connect(this->verticalScrollBar(), &QScrollBar::valueChanged, m_verticalScrollBar, &QScrollBar::setValue); connect(m_verticalScrollBar, &QScrollBar::sliderMoved, this->verticalScrollBar(), &QScrollBar::setSliderPosition); connect(m_verticalScrollBar, &QScrollBar::valueChanged, this->verticalScrollBar(), &QScrollBar::setValue); m_verticalScrollBar->hide(); m_verticalScrollBar->setContextMenuPolicy(Qt::NoContextMenu); connect(model(), &QAbstractItemModel::dataChanged, this, &TableViewEx::OnScrollBarDataChanged, Qt::UniqueConnection); connect(model(), &QAbstractItemModel::modelReset, this, &TableViewEx::OnModelReset, Qt::UniqueConnection); } else { if(m_verticalScrollBar != nullptr) { delete m_verticalScrollBar; m_verticalScrollBar = nullptr; } } } void TableViewEx::SetHorizontalScrollBar(bool bIsNeed) { if(bIsNeed && m_horizontalScrollBar == nullptr) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //自定义滚动条 m_horizontalScrollBar = new QScrollBar(Qt::Orientation::Horizontal, this); connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, m_horizontalScrollBar, &QScrollBar::setValue); connect(m_horizontalScrollBar, &QScrollBar::sliderMoved, this->horizontalScrollBar(), &QScrollBar::setSliderPosition); connect(m_horizontalScrollBar, &QScrollBar::valueChanged, this->horizontalScrollBar(), &QScrollBar::setValue); m_horizontalScrollBar->hide(); m_horizontalScrollBar->setContextMenuPolicy(Qt::NoContextMenu); connect(model(), &QAbstractItemModel::dataChanged, this, &TableViewEx::OnScrollBarDataChanged, Qt::UniqueConnection); connect(model(), &QAbstractItemModel::modelReset, this, &TableViewEx::OnModelReset, Qt::UniqueConnection); } else { if(m_horizontalScrollBar != nullptr) { delete m_horizontalScrollBar; m_horizontalScrollBar = nullptr; } } }