QTreeView:resizeRowsToContents 等效或如何在行中自动换行文本

QTreeView: resizeRowsToContents equivalent or how to word-wrap text in rows

我有一个包含多个列的 QTreeView(例如 table)。树中的列具有固定大小。我需要调整行高并使用 QTableView::resizeRowsToContents 等多行文本。 我该怎么做?

我尝试使用自定义 QStyledItemDelegate 并重新实现 sizeHint,但我不知道如何计算已知宽度的多行文本块高度。

使用QStyledItemDelegate 是正确的方法。在您的 sizeHint 函数中,您可以使用样式选项 text with the QFontMetrics class:

QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override {
    QSize baseSize = this->QStyledItemDelegate::sizeHint(option, index);
    baseSize.setHeight(10000);//something very high, or the maximum height of your text block

    QFontMetrics metrics(option.font);
    QRect outRect = metrics.boundingRect(QRect(QPoint(0, 0), baseSize), Qt::AlignLeft, option.text);
    baseSize.setHeight(outRect.height());
    return baseSize;
}

注意:现在我无法测试它,但它应该可以工作。如果输出不符合您的需要,您可能需要调整对 metrics.boundingRect 的调用

编辑:
sizeHint 似乎只会被调用一次来创建初始布局,但不会在调整列的大小后调用。

最终的想法可能是使用 Qt::SizeHintRoleQAbstractItemModel::data 函数覆盖为 return 所需的大小。您可以将其添加到现有模型或提供代理模型来执行此操作:

QSize MyModel::data(const QModelIndex &index, int role) const override {
    switch(role) {
        //...
    case Qt::SizeHintRole:
    {
        QSize baseSize(getFixedWidth(index.column()), baseSize.setHeight(10000));//something very high, or the maximum height of your text block

        QFontMetrics metrics(this->data(index, Qt::FontRole).value<QFont>());
        QRect outRect = metrics.boundingRect(QRect(QPoint(0, 0), baseSize), Qt::AlignLeft, this->data(index, Qt::DisplayRole)));
        baseSize.setHeight(outRect.height());
        return baseSize;
    }
        //...
    }
}

重要提示:每次调整视图大小时,您都必须为所有这些项目发出 dataChanged 信号。 getFixedWidth 是你必须实现的东西 return 给定列的当前宽度。