QTableView 标题自动换行

问题描述 投票:0回答:5

我试图将 QTableView 中的水平和垂直标题设置为自动换行,但没有成功。

我想将所有列设置为相同的宽度(包括垂直标题),并将那些具有多行文本的列设置为自动换行。如果单词比列宽,则应向右删除。 我已经设法使用 QTableView ->horizontalHeader() ->setTextElideMode(Qt::ElideRight) 设置 elide,但我无法对自动换行执行相同的操作,因为 QHeaderView 没有 setWordWrap 方法。因此,如果文本是多行,它就会被删除。在表视图上设置自动换行不会执行任何操作。表格单元格仅包含少量数字,因此问题仅与标题有关,并且我想避免使用“/n”,因为标题是动态设置的。我是否更改了其他一些设置,不允许自动换行运行?

qt
5个回答
6
投票

我能够整合上面的两种方法(c++,Qt 5.12),并获得相当不错的结果。 (模型上没有隐藏标题)

  1. 覆盖
    QHeaderView::sectionSizeFromContents()
    ,使大小考虑文本换行
QSize MyHeaderView::sectionSizeFromContents(int logicalIndex) const 
{
    const QString text = this->model()->headerData(logicalIndex, this->orientation(), Qt::DisplayRole).toString();
    const int maxWidth = this->sectionSize(logicalIndex);
    const int maxHeight = 5000; // arbitrarily large
    const auto alignment = defaultAlignment();
    const QFontMetrics metrics(this->fontMetrics());
    const QRect rect = metrics.boundingRect(QRect(0, 0, maxWidth, maxHeight), alignment, text);

    const QSize textMarginBuffer(2, 2); // buffer space around text preventing clipping
    return rect.size() + textMarginBuffer;
}
  1. 设置默认对齐方式以自动换行(可选,居中)
 tableview->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter | (Qt::Alignment)Qt::TextWordWrap);

3
投票

我设法使用

QHeaderView
的子类化并重新实现其中的
sectionSizeFromContents
paintSection
方法找到了解决方案。这是 PyQt5 中的演示(使用 Python 3.5.2 和 Qt 5.6 进行测试):

import sys
import string
import random
from PyQt5 import QtCore, QtWidgets, QtGui

class HeaderViewWithWordWrap(QtWidgets.QHeaderView):
    def __init__(self):
        QtWidgets.QHeaderView.__init__(self, QtCore.Qt.Horizontal)

    def sectionSizeFromContents(self, logicalIndex):
        if self.model():
            headerText = self.model().headerData(logicalIndex,
                                                 self.orientation(),
                                                 QtCore.Qt.DisplayRole)
            options = self.viewOptions()
            metrics = QtGui.QFontMetrics(options.font)
            maxWidth = self.sectionSize(logicalIndex)
            rect = metrics.boundingRect(QtCore.QRect(0, 0, maxWidth, 5000),
                                        self.defaultAlignment() |
                                        QtCore.Qt.TextWordWrap |
                                        QtCore.Qt.TextExpandTabs,
                                        headerText, 4)
            return rect.size()
        else:
            return QtWidgets.QHeaderView.sectionSizeFromContents(self, logicalIndex)

    def paintSection(self, painter, rect, logicalIndex):
        if self.model():
            painter.save()
            self.model().hideHeaders()
            QtWidgets.QHeaderView.paintSection(self, painter, rect, logicalIndex)
            self.model().unhideHeaders()
            painter.restore()
            headerText = self.model().headerData(logicalIndex,
                                                 self.orientation(),
                                                 QtCore.Qt.DisplayRole)
            painter.drawText(QtCore.QRectF(rect), QtCore.Qt.TextWordWrap, headerText)
        else:
            QtWidgets.QHeaderView.paintSection(self, painter, rect, logicalIndex)

class Model(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.model_cols_names = [ "Very-very long name of my first column",
                                  "Very-very long name of my second column",
                                  "Very-very long name of my third column",
                                  "Very-very long name of my fourth column" ]
        self.hide_headers_mode = False
        self.data = []
        for i in range(0, 10):
            row_data = []
            for j in range(0, len(self.model_cols_names)):
                row_data.append(''.join(random.choice(string.ascii_uppercase +
                                        string.digits) for _ in range(6)))
            self.data.append(row_data)

    def hideHeaders(self):
        self.hide_headers_mode = True

    def unhideHeaders(self):
        self.hide_headers_mode = False

    def rowCount(self, parent):
        if parent.isValid():
            return 0
        else:
            return len(self.data)

    def columnCount(self, parent):
        return len(self.model_cols_names)

    def data(self, index, role):
        if not index.isValid():
            return None
        if role != QtCore.Qt.DisplayRole:
            return None

        row = index.row()
        if row < 0 or row >= len(self.data):
            return None

        column = index.column()
        if column < 0 or column >= len(self.model_cols_names):
            return None

        return self.data[row][column]

    def headerData(self, section, orientation, role):
        if role != QtCore.Qt.DisplayRole:
            return None
        if orientation != QtCore.Qt.Horizontal:
            return None
        if section < 0 or section >= len(self.model_cols_names):
            return None
        if self.hide_headers_mode == True:
            return None
        else:
            return self.model_cols_names[section]

class MainForm(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.model = Model()
        self.view = QtWidgets.QTableView()
        self.view.setModel(self.model)
        self.view.setHorizontalHeader(HeaderViewWithWordWrap())
        self.setCentralWidget(self.view)

def main():
    app = QtWidgets.QApplication(sys.argv)
    form = MainForm()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

3
投票

在Python中:

myTableView.horizontalHeader().setDefaultAlignment(Qt.AlignCenter | Qt.Alignment(Qt.TextWordWrap))


1
投票
2010 年的一个

open Qt issues 表明这可能不容易实现。 然而,根据 2015 年的唯一评论,对于这个问题有一个简单的解决方法,如下所示:

myTable->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter | (Qt::Alignment)Qt::TextWordWrap);

我刚刚使用 Qt 5.12 进行了测试,幸运的是发现它仍然可以工作。


0
投票
Jayme Gordon 答案可以移植到 Qt6 (PySide6),如下所示:

horizontalHeader().setDefaultAlignment(Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap)
    
© www.soinside.com 2019 - 2024. All rights reserved.