qtreeview更新item行宽和高
# qtreeview delegate 中item显示
有时候qtreeview的一个item的文字长度很长时,一般Qt都会缩略他,比如“suncaiyusuncaiyusuncaiyusuncaiyusuncaiyusuncaiyu”会根据策略比如Qt::ElideRight缩成“suncai...”这种。 如果我就是想把它全部显示出来,有两种模式:
# 1.显示在一行上,全部显示
# 1.第一个办法
此时Qt有一个方法,叫
[slot] void QTreeView::resizeColumnToContents(int column) Resizes the column given to the size of its contents. See also columnWidth(), setColumnWidth(), sizeHintForColumn(), and QHeaderView::resizeContentsPrecision(). 他会自动帮你计算。 但是需要注意的是。 resizeColumnToContents有两个相关属性
- enum QHeaderView::ResizeMode 列表头的resize模式有一个QHeaderView::ResizeToContents跟随内容一个调整
- void QHeaderView::setResizeContentsPrecision(int precision) 调整精度:有点抽象,表示resizeColumnToContents作用的行数。因为treeview有很多行的,precision参数表示作用多少行。比如默认1000 他就会调整1000行,后面的就不管了。特殊值-1表示作用全部行。但是如果有很多数据,这回很耗时间。特殊值0表示值作用当前可见的区域,但这就以为这你要多次刷新,调用resizeColumnToContents。
# 2.第二个办法
自己计算。 其实一行的宽度是根据QTreeview的QHeadView决定的 我们可以在sizeHint中,获取到index对应的font,以及显示的数据,用QFontMertricx计算显示这行数据需要多长的宽度,然后QHeadView::resizeSection()设置header的宽度。(具体没有多测试,可能会有一些小问题,可以看着解决)
# 2. 分行显示,根据header的宽度,自动调整行高度,以便显示全部文字
虽然QTreeView中有一个叫WordWrap的属性,但是设置后发现,没有啥用。而且官方说明里也写了,他并不对全部列管用。(好用只对主列有用) 那就只能自己想办法。还是参考上面第二种办法。首先设置
void setUniformRowHeights(bool uniform)
为false,因为我们不能保证所有行高度一致。 还是在delegate的sizehint中获取header的对应宽度
int wordWidth = fm.width(str); // 显示需要的宽度
int lineCount = wordWidth / headerWidth; // 如果换行,需要多少行
if (wordWidth % heaferWidth > 0) {
lineCount++;
}
QSize sz;
sz.setHeight(lineCount * fm.height() + (lineCount + 1) * fm.lineSpacing));
return sz;
2
3
4
5
6
7
8
同时在delegete中的painter函数中,自己paint一下
if (index.column() == 你需要绘制的那行) {
painter.drawText(option.rect, Qt::TextWrapAnywhere | Qt::AlignVCenter, index.data(Qt::DisplayRole).value<QString>());
}
2
3
如果想要两边留点距离可以option.rect.adjusted(5, 0, 0, -5),当然,在sizeHint计算lineCount的术后需要吧对应的 10像素减去。
但是还有一个最重要的点,当你拖动调整header()的宽度的时候,他是不会变化的,因为没有通知它更新。理论上在delegate中,所有的size变化,都需要发送一个系统的sizeHintChanged(QModelIndex())信号。 或者调用一个偏门的函数 doItemsLayout();