方法二:
重寫代理painter方法,發送消息給QTableView重置行大小resizeRowToContents,然後代理會調用sizeHint(根據幫助文檔上說此方法傳回大小作為參考值),需要計算出内容所需高度(計算有兩種方法請看代碼)
優點:比方法一簡單、代碼少,隻會計算可視行
缺點:如果資料是變化的,則一直在計算(可以優化已經計算過且字元串沒有變化的就不再計算和重置大小)
QTableView*mTableView = new QTableView(false, this);
mTableView->horizontalHeader()->setVisible(true);
ItemDelegate *mDelegate = new ItemDelegate(mTableView);
mTableView->setItemDelegate(mDelegate);
connect(mDelegate, &ItemDelegate::SignalResizeRowHeight, mTableView, &QTableView::resizeRowToContents);
#pragma once
#include <QEvent>
#include <QPainter>
#include <QApplication>
#include <QStyledItemDelegate>
class ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ItemDelegate(QObject* parent) :QStyledItemDelegate(parent)
{
connect(this, &DataStreamItemDelegate::SignalResizeRow, this, [=](const int32_t& h, const QModelIndex& index)
{
//算法:除第一列行最高
int col = index.column();
int row = index.row();
FXD << row <<" "<< col ;
if (col == 0)
{
mHeights.clear(); //每次重置行資料,保證行高可以增高或者縮小
if (mColumnsHeight.keys().contains(row))
{
return;
}
mRowMaxHeight = h;
mColumnsHeight.insert(row, h);
}
else
{
//得到除去第一列的行最大高度
if (mHeights.value(row) >= h)
{
mRowMaxHeight = mHeights.value(row);
}
else
{
mHeights.insert(row, h);
mRowMaxHeight = h;
}
//與第一列行高度比較得到最大高度,即為本行最大高度
if (mColumnsHeight.value(row) > mRowMaxHeight) //一般情況第一行内容最多
{
mRowMaxHeight = mColumnsHeight.value(row);
}
}
emit SignalResizeRowHeight(row);
});
}
virtual~ItemDelegate() {}
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
FXD;
QStyleOptionViewItem itemOption(option);
initStyleOption(&itemOption, index);
if (itemOption.state & QStyle::State_HasFocus)
{
itemOption.state &= ~QStyle::State_HasFocus; // 去除焦點虛線
}
if (itemOption.state & QStyle::State_MouseOver)
{
itemOption.state &= ~QStyle::State_MouseOver;
}
if (option.state.testFlag(QStyle::State_Selected))
{
itemOption.state &= ~QStyle::State_Selected;
}
if (!index.isValid())
{
return;
}
painter->save();
QStyledItemDelegate::paint(painter, itemOption, index);
painter->setPen(QPen(QBrush(QColor(0xD8, 0xD8, 0xD8)), HOR_LINE_WIDTH, ((QTableView*)tableView)->gridStyle()));
painter->drawLine(itemOption.rect.bottomLeft(), itemOption.rect.bottomRight());
painter->restore();
paint(painter, option, index);
if (option.rect.width() <= 0)
{
return;
}
QString data = index.model()->data(index, Qt::UserRole).value<QString>();
painter->save();
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));
painter->setFont(option.font);
QTextOption toption(Qt::AlignLeft);
toption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
painter->drawText(option.rect.adjusted(mPadding, mPadding, -mPadding, -mPadding), data, toption);
painter->restore();
//計算内容所需高度方法一
int col = index.column();
int row = index.row();
if (col == 0) //第一列隻計算一次
{
if (!mColumnsHeight.keys().contains(row))
{
QRect rect = option.rect.adjusted(mPadding, 0, -mPadding, 0);
rect.setHeight(500);
painter->setFont(option.font);
rect = painter->boundingRect(rect, data, toption).toRect();
rect.setHeight(rect.height() + mPadding * 2);
emit SignalResizeRow(rect.height(), index);
}
}
else
{
QRect rect = option.rect.adjusted(mPadding, 0, -mPadding, 0);
rect.setHeight(500);
painter->setFont(option.font);
rect = painter->boundingRect(rect, data, toption).toRect();
rect.setHeight(rect.height() + mPadding * 2);
emit SignalResizeRow(rect.height(), index);
}
}
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
if (option.rect.width() <= 0)
{
return QStyledItemDelegate::sizeHint(option, index);
}
FXD;
//計算内容所需高度方法二,此方法有一個弊端 [參考我這篇文章](https://blog.csdn.net/u011100345/article/details/115914781)
//QString data = index.model()->data(index, Qt::UserRole).value<QString>();
//QRect rect = option.rect.adjusted(mPadding,0,-mPadding,0);
//rect.setHeight(500);
//rect = QFontMetrics(option.font).boundingRect(rect, Qt::TextWordWrap | Qt::TextWrapAnywhere, data); //
//rect.setHeight(rect.height() + mPadding * 2);
QSize size = QStyledItemDelegate::sizeHint(option, index);
if (mRowMaxHeight > mRowHeight)
{
size.setHeight(mRowMaxHeight);
}
return size;
}
signals:
void SignalResizeRow(const int32_t& h, const QModelIndex& row)const;
void SignalResizeRowHeight(const int32_t& row);
private:
int32_t mPadding = 16; //内容上下左右空隙
int32_t mRowMaxHeight = 0;
QMap<int32_t, int32_t> mHeights; //其他列對應行最大高度
QMap<int32_t, int32_t> mColumnsHeight;//資料流第一列隻計算一次存儲用于後續比較<行号-高度>
};