ttomLeft(), viewport()->rect().bottomRight());
}
b、列宽发生变化
void HHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
{
if (0 == newSize)
{
//过滤掉隐藏列导致的resize
viewport()->update();
return;
}
static bool selfEmitFlag = false;
if (selfEmitFlag)
{
return;
}
int minWidth = 99999;
QFontMetrics metrics(font());
//获取这列上最小的字体宽度,移动的长度不能大于最小的字体宽度
HHeaderModel * model = qobject_cast<HHeaderModel *> (this->model());
for (int i = 0; i < model->rowCount(QModelIndex()); ++i)
{
QString text = model->item(i, logicalIndex);
if (text.isEmpty())
continue;
int textWidth = metrics.width(text);
if (minWidth > textWidth)
{
minWidth = textWidth;
}
}
if (newSize < minWidth)
{
selfEmitFlag = true;
resizeSection(logicalIndex, oldSize);
selfEmitFlag = false;
}
viewport()->update();
}
3、QStyledItemDelegate绘制代理
既然说到了自绘,那么有必要说下Qt自绘相关的一些东西。
a、paintEvent
paintEvent是QWidget提供的自绘函数,当界面刷新时该接口就会被调用。
b、复杂控件自绘
对于一些比较复杂的控件为了达到更好的定制型,Qt把paintEvent函数中的绘制过程进行了更为详细的切割,也可以让我们进行布局的重写。
比如今天说到的树控件,当paintEvent函数调用时,其实内部真正进行绘制的是如下3个函数,重写如下三个函数可以为我们带来更友好的定制性,并且很大程度上减轻了我们自己去实现的风险。
virtual void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const
virtual void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
void drawTree(QPainter *painter, const QRegion ®ion) const
c、QStyledItemDelegate绘制代理
为了更好的代码管理和接口抽象,Qt在处理一些超级变态的控件时提供了绘制代理这个类,即使在一些力度很小的绘制函数中依然是调用的绘制代理去绘图。
刚好我们今天说的这个表头绘制就是如此。如下代码所示,是一部分的HHeaderItemDelegate::paint函数展示,主要是针对表头排序进行了定制。
void HHeaderItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
int row = index.row();
int col = index.column();
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
QStyleOptionHeader header_opt;
header_opt.rect = option.rect;
header_opt.position = QStyleOptionHeader::Middle;
header_opt.textAlignment = Qt::AlignCenter;
header_opt.state = option.state;
//header_opt.state |= QStyle::State_HasFocus;//QStyle::State_Enabled | QStyle::State_Horizontal | QStyle::State_None | QStyle::State_Raised;
if (HHeaderView::instance->isItemPress(row, col))
{
header_opt.state |= QStyle::State_Sunken; //按钮按下效果
}
// if ((QApplication::mouseButtons() && (Qt::LeftButton || Qt::RightButton)))
// header_opt.state |= QStyle::State_Sunken;
painter->save();
QApplication::style()->drawControl(QStyle::CE_Header, &header_opt, painter);
painter->restore();
}
五、测试代码
把需要合并的列和行进行合并,即可达到多级表头的效果,如下是设置表格model合并接口展示。
horizontalHeaderModel->setSpan(0, 0, 1, 4);
horizontalHeaderModel->setSpan(0, 4, 1, 3);
horizontalHeaderModel->setSpan(0, 7, 1, 3);
horizontalHeaderModel->setSpan(0, 10, 2, 1);
horizontalHeaderModel->setSpan(0, 11, 2, 1); //不支持跨越多行多列的情况
}
model设置完毕后只要把Model设置给QHeaderView类即可。
六、相关文章
值得一看的优秀文章:
- 财联社-产品展示
- 广联达-产品展示
- Qt定制控件列表
- 牛逼哄哄的Qt库
Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等
Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格
属性浏览器控件QtTreePropertyBrowser编译成动态库(设计师插件)
超级实用的属性浏览器控件--QtTreePropertyBrowser
Qt之表格控件蚂蚁线
QRowTable表格控件-支持hover整行、checked整行、指定列排序等
如果