tableviewex.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "tableviewex.h"
  2. #include <QScrollBar>
  3. #include <QTimer>
  4. #include <QHeaderView>
  5. TableViewEx::TableViewEx(QWidget *parent)
  6. : QTableView(parent)
  7. {
  8. //设置model
  9. setModel(&m_model);
  10. //设置所有单元格不可编辑(注意: 设计器里不能设置, 否则这里的设置不生效, 因为在setupUi里先执行了构造函数再执行设置方法)
  11. setEditTriggers(QAbstractItemView::NoEditTriggers);
  12. //设置右键菜单模式(注意: 设计器里不能设置, 否则这里的设置不生效, 因为在setupUi里先执行了构造函数再执行设置方法)
  13. setContextMenuPolicy(Qt::CustomContextMenu);
  14. //禁用滚动条右键菜单
  15. verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
  16. horizontalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu);
  17. //冻结横向滚动条, 否则点击未完全显示的单元格时, 表格会自动滚动来让单元格完全显示
  18. // setHorizontalScrollBar(new FrozenScrollBar(this));
  19. //选中时选中一行
  20. setSelectionBehavior(QAbstractItemView::SelectRows);
  21. //SetDragEnable(false);
  22. }
  23. void TableViewEx::ClearModel()
  24. {
  25. m_model.clear();
  26. SetHeaders();
  27. //m_model.ClearHTMLContent();
  28. }
  29. bool TableViewEx::RemoveRow(int row)
  30. {
  31. bool isSelected = (currentIndex().row() == row);
  32. //这里使用model()来删除, 如果使用了代理model, 删除代理model的时候, 源model的行也会被删除
  33. model()->removeRow(row);
  34. if(isSelected && model()->rowCount() != 0)
  35. {
  36. SetCurrentRow(0);
  37. }
  38. if(m_verticalScrollBar != nullptr)
  39. {
  40. QModelIndex topLeft = model()->index(row, 0);
  41. QModelIndex bottomRight = model()->index(row, model()->columnCount() - 1);
  42. emit model()->dataChanged(topLeft, bottomRight);
  43. }
  44. return true;
  45. }
  46. bool TableViewEx::RemoveRow(const QModelIndex &index)
  47. {
  48. return RemoveRow(index.row());
  49. }
  50. bool TableViewEx::IsEmpty(bool forSourceModel)
  51. {
  52. QAbstractItemModel *pModel = GetModel(forSourceModel);
  53. return (pModel->rowCount() == 0);
  54. }
  55. void TableViewEx::SetCurrentRow(int row)
  56. {
  57. /*----------------------------------------------------------------
  58. * 这里必须要使用model()->index(..)来获取index, 因为model()取到的才是实际的model
  59. * 假如这个tableview使用了代理model, 则model()是代理的model, 而m_model则是源model
  60. ----------------------------------------------------------------*/
  61. setCurrentIndex(model()->index(row, 0));
  62. }
  63. QAbstractItemModel *TableViewEx::GetModel(bool sourceModel)
  64. {
  65. return sourceModel?(&m_model):model();
  66. }
  67. void TableViewEx::OnScrollBarDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
  68. {
  69. Q_UNUSED(topLeft);
  70. Q_UNUSED(bottomRight);
  71. Q_UNUSED(roles);
  72. if(m_verticalScrollBar != nullptr)
  73. {
  74. //获取视图的大小
  75. QSize viewportSize = viewport()->size();
  76. //获取总行数
  77. int nRowCount = model()->rowCount();
  78. int nTotalRowHeight = 0;
  79. //计算总行高
  80. for(int row = 0; row < nRowCount; ++row)
  81. {
  82. nTotalRowHeight += rowHeight(row);
  83. }
  84. //判断是否需要显示滚动条
  85. bool bNeedScrollBar = nTotalRowHeight > viewportSize.height();
  86. QTimer::singleShot(0, this, [=]() {
  87. if(bNeedScrollBar)
  88. {
  89. //判断表头是否显示
  90. if(horizontalHeader()->isVisible())
  91. {
  92. //在布局完成后设置垂直滚动条范围
  93. m_verticalScrollBar->resize(QSize(6, height() - 48));
  94. m_verticalScrollBar->move(width() - 6, 48);
  95. m_verticalScrollBar->setRange(this->verticalScrollBar()->minimum(), this->verticalScrollBar()->maximum());
  96. m_verticalScrollBar->show();
  97. }
  98. else
  99. {
  100. //在布局完成后设置垂直滚动条范围
  101. m_verticalScrollBar->resize(QSize(6, height()));
  102. m_verticalScrollBar->move(width() - 6, 0);
  103. m_verticalScrollBar->setRange(this->verticalScrollBar()->minimum(), this->verticalScrollBar()->maximum());
  104. m_verticalScrollBar->show();
  105. }
  106. }
  107. else
  108. {
  109. m_verticalScrollBar->hide();
  110. }
  111. });
  112. }
  113. if(m_horizontalScrollBar != nullptr)
  114. {
  115. //获取视图的大小
  116. QSize viewportSize = viewport()->size();
  117. //获取总列数
  118. int nColCount = model()->columnCount();
  119. QTimer::singleShot(0, this, [=]() {
  120. int nTotalColWidth = 0;
  121. //计算总列宽
  122. for(int col = 0; col < nColCount; ++col)
  123. {
  124. nTotalColWidth += columnWidth(col);
  125. }
  126. //判断是否需要显示滚动条
  127. bool bNeedScrollBar = nTotalColWidth > viewportSize.width();
  128. if(bNeedScrollBar)
  129. {
  130. //在布局完成后设置横向滚动条范围
  131. m_horizontalScrollBar->resize(QSize(width(), 6));
  132. m_horizontalScrollBar->move(0, height() - 6);
  133. m_horizontalScrollBar->setRange(this->horizontalScrollBar()->minimum(), this->horizontalScrollBar()->maximum());
  134. m_horizontalScrollBar->show();
  135. }
  136. else
  137. {
  138. m_horizontalScrollBar->hide();
  139. }
  140. });
  141. }
  142. }
  143. void TableViewEx::OnModelReset()
  144. {
  145. if(m_verticalScrollBar)
  146. {
  147. m_verticalScrollBar->hide();
  148. }
  149. if(m_horizontalScrollBar)
  150. {
  151. m_horizontalScrollBar->hide();
  152. }
  153. }
  154. void TableViewEx::SetVerticalScrollBar(bool bIsNeed)
  155. {
  156. if(bIsNeed && m_verticalScrollBar == nullptr)
  157. {
  158. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  159. //自定义滚动条
  160. m_verticalScrollBar = new QScrollBar(Qt::Orientation::Vertical, this);
  161. connect(this->verticalScrollBar(), &QScrollBar::valueChanged, m_verticalScrollBar, &QScrollBar::setValue);
  162. connect(m_verticalScrollBar, &QScrollBar::sliderMoved, this->verticalScrollBar(), &QScrollBar::setSliderPosition);
  163. connect(m_verticalScrollBar, &QScrollBar::valueChanged, this->verticalScrollBar(), &QScrollBar::setValue);
  164. m_verticalScrollBar->hide();
  165. m_verticalScrollBar->setContextMenuPolicy(Qt::NoContextMenu);
  166. connect(model(), &QAbstractItemModel::dataChanged, this, &TableViewEx::OnScrollBarDataChanged, Qt::UniqueConnection);
  167. connect(model(), &QAbstractItemModel::modelReset, this, &TableViewEx::OnModelReset, Qt::UniqueConnection);
  168. }
  169. else
  170. {
  171. if(m_verticalScrollBar != nullptr)
  172. {
  173. delete m_verticalScrollBar;
  174. m_verticalScrollBar = nullptr;
  175. }
  176. }
  177. }
  178. void TableViewEx::SetHorizontalScrollBar(bool bIsNeed)
  179. {
  180. if(bIsNeed && m_horizontalScrollBar == nullptr)
  181. {
  182. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  183. //自定义滚动条
  184. m_horizontalScrollBar = new QScrollBar(Qt::Orientation::Horizontal, this);
  185. connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, m_horizontalScrollBar, &QScrollBar::setValue);
  186. connect(m_horizontalScrollBar, &QScrollBar::sliderMoved, this->horizontalScrollBar(), &QScrollBar::setSliderPosition);
  187. connect(m_horizontalScrollBar, &QScrollBar::valueChanged, this->horizontalScrollBar(), &QScrollBar::setValue);
  188. m_horizontalScrollBar->hide();
  189. m_horizontalScrollBar->setContextMenuPolicy(Qt::NoContextMenu);
  190. connect(model(), &QAbstractItemModel::dataChanged, this, &TableViewEx::OnScrollBarDataChanged, Qt::UniqueConnection);
  191. connect(model(), &QAbstractItemModel::modelReset, this, &TableViewEx::OnModelReset, Qt::UniqueConnection);
  192. }
  193. else
  194. {
  195. if(m_horizontalScrollBar != nullptr)
  196. {
  197. delete m_horizontalScrollBar;
  198. m_horizontalScrollBar = nullptr;
  199. }
  200. }
  201. }