微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

动态自动调整QTableView水平标题高度

如何解决动态自动调整QTableView水平标题高度

我试图让 - --command - docker run --privileged 在列宽改变时自动调整高度,我已经对 QTableView 进行了子分类,但我无法实际使用它,我正在使用 {每当更改列宽时,{1}} 的 {1}} 信号,并根据新列和列标题的字符串长度,我试图估计高度。

QHeaderView

我实际上不确定我是否走在正确的道路上,试图通过在部分调整大小事件上调用 sectionResized 来更改标题的高度,我一直在寻找 QHeaderView docs 但是我无法弄清楚需要覆盖 QHeaderView方法才能完成此操作。

编辑

我没有手动尝试估计高度,这不是一个好主意,而是使用了 QHeaderView.sectionSizeFromContentsfrom pyside2.QtCore import * from pyside2.QtWidgets import * class HeaderView(QHeaderView): def __init__(self,parent): super(HeaderView,self).__init__(Qt.Horizontal,parent) self.setStyleSheet( "QHeaderView::section{background-color: #ffffff; " "font-weight: bold; " "padding-left: 2px; " "color: #3467ba; " "border:0px; " "border-left: 1px solid #ababab; " "border-bottom: 1px solid gray;}") self.setStretchLastSection(True) self.setDefaultAlignment(Qt.AlignCenter|Qt.Alignment(Qt.TextWordWrap)) class TableView(QTableView): def __init__(self,parent=None): super(TableView,self).__init__(parent) self.setAlternatingRowColors(True) self.setShowGrid(False) model = DataModel(self) self.setModel(model) self.setWordWrap(True) self._headerView = HeaderView(self) self._headerView.sectionResized.connect(self.resizeColumns) self.setHorizontalHeader(self._headerView) self.resize(800,400) def resizeColumns(self,idx,oldSize,newSize): """ widthEstimation = length of character for header multiplied by 10 for each column estimatedHeight = (estimatedWidth*10/columnwidth) + 5 for each column (the assumption is (estimatedWidth/columnWidth) gives number of line required for the header text) """ widthEstimation = [len(self.model().headerData(colIdx))*10 for colIdx in range(self.model().columnCount())] estimatedHeight = max(estimatedWidth*10//self.columnWidth(colIdx)+5 for colIdx,estimatedWidth in enumerate(widthEstimation)) self._headerView.setMinimumHeight(estimatedHeight) class DataModel(QAbstractTableModel): def __init__(self,parent): super(DataModel,self).__init__(parent) #Setting some static data self._data = [['Dummy-01-0001','M','41.01026694045174','NOT HISPANIC OR LATINO','Albumin (g/L)','N'] for _ in range(5)]+\ [['Dummy-01-0001','F','HISPANIC OR LATINO','Chloride (mmol/L)','Y'] for _ in range(5)] self._header = ['Unique Subject Identifier (USUBJID)','Sex (SEX)','Age (AGE)','Ethnicity (ETHNIC)','Parameter (ParaM)','Analysis Reference Range Indicator (ANRIND)'] def rowCount(self,parent=None): return len(self._data) def columnCount(self,parent=None): return len(self._header) def data(self,index,role=Qt.displayRole): if index.isValid() and role==Qt.displayRole: return str(self._data[index.row()][index.column()]) def headerData(self,section,orientation:Qt.Horizontal = Qt.Horizontal,role=Qt.displayRole): if orientation == Qt.Horizontal: if role == Qt.displayRole: return self._header[section] # elif role == Qt.TextAlignmentRole and section==0: # return Qt.AlignLeft|Qt.Alignment(Qt.TextWordWrap) def flags(self,index): if index.isValid(): return Qt.ItemIsEnabled | Qt.ItemIsSelectable if __name__ == "__main__": import sys app = QApplication() widg = TableView() widg.show() sys.exit(app.exec_()) ;它给了我比以前更好的结果,但我仍然不确定如何去做。

我尝试将 setMinimumHeight 除以实际的 QHeaderView,这样可以更好地估计标题字符串所需的行数,将其乘以 fontMetrics() 加上 5 个像素作为偏移量.

sectionSizefromContent

编辑

我尝试在 Qt 论坛上提问,@SGiast 提出了确定给定列标题的边界矩形的想法,覆盖 sectionSizesectionSizeFromContents 方法;确定每个部分所需的最小宽度和标题所需的最大高度很有帮助:

fontMertircs().height()

该线程在 Qt Forum 处于活动状态

解决方法

最后,通过一些互联网搜索,以及在 @SGiast 的 Qt 论坛上使用 fontMetrics 和从 How to make QTableView to adjust the height of it's horizontal header automatically in PyQt? 确定边界矩形的想法,并在 SO thread: How to use QFontMetrics boundingRect to measure size? 的帮助下,我得到了能够实现所需的行为。

class HeaderView(QHeaderView):
    def __init__(self,parent=None):
        super().__init__(Qt.Horizontal,parent=parent)
        self.setStyleSheet(
            "QHeaderView::section{background-color: #ffffff; "
            "font-weight: bold; "
            "color: #3467ba; "
            "border:0px; "
            "border-left: 1px solid #ababab; "
            "border-bottom: 1px solid gray;}"
        )
        self.setStretchLastSection(True)
        self.setDefaultAlignment(Qt.AlignCenter | Qt.Alignment(Qt.TextWordWrap))
        self._setMaxHeight()

    def sectionHeight(self,logicalIndex):
        return (self.fontMetrics().boundingRect(QRect(0,self.sectionSize(logicalIndex)-10,self._MAXHEIGHT),self.defaultAlignment(),self.model().headerData(logicalIndex))).height()

    def _setMaxHeight(self):
        self._MAXHEIGHT = max(l.height() for l in (self.fontMetrics().boundingRect(QRect(),self.parent().model().headerData(i)) for i in range(self.parent().model().columnCount())))


class TableView(QTableView):
    def __init__(self,parent=None):
        super(TableView,self).__init__(parent)
        self.setAlternatingRowColors(True)
        self.setShowGrid(False)
        model = DataModel(self)
        self.setModel(model)
        self.setWordWrap(True)
        self._headerView = HeaderView(self)
        self._headerView.sectionResized.connect(self.resizeColumns)
        self.setHorizontalHeader(self._headerView)
        self.resize(800,400)

        self._widths = []


    def resizeColumns(self,idx,oldSize,newSize):
        minH = min(self._headerView._MAXHEIGHT,max(self._headerView.sectionHeight(i) for i in range(self.model().columnCount())))
        self._headerView.setMinimumHeight(minH)
        print(minH)

class DataModel(QAbstractTableModel):
    def __init__(self,parent):
        super(DataModel,self).__init__(parent)
        #Setting some static data
        self._data = [['Dummy-01-0001','M','41.01026694045174','NOT HISPANIC OR LATINO','Albumin (g/L)','N'] for _ in range(5)]+\
                     [['Dummy-01-0001','F','HISPANIC OR LATINO','Chloride (mmol/L)','Y'] for _ in range(5)]
        self._header = ['Unique Subject Identifier (USUBJID)','Sex (SEX)','Age (AGE)','Ethnicity (ETHNIC)','Parameter (PARAM)','Analysis Reference Range Indicator (ANRIND)']

    def rowCount(self,parent=None):
        return len(self._data)

    def columnCount(self,parent=None):
        return len(self._header)

    def data(self,index,role=Qt.DisplayRole):
        if index.isValid() and role==Qt.DisplayRole:
            return str(self._data[index.row()][index.column()])

    def headerData(self,section,orientation:Qt.Horizontal = Qt.Horizontal,role=Qt.DisplayRole):
        if orientation == Qt.Horizontal:
            if role == Qt.DisplayRole:
                return self._header[section]
            # elif role == Qt.TextAlignmentRole and section==0:
            #     return Qt.AlignLeft|Qt.Alignment(Qt.TextWordWrap)

    def flags(self,index):
        if index.isValid():
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable


if __name__ == "__main__":
    import sys
    app = QApplication()
    widg = TableView()
    widg.show()
    sys.exit(app.exec_())

我在 HeaderView 类中创建了两个方法,方法 _setMaxHeight 给出了当每列中的文本具有最大换行时标题最大高度的估计,标题高度将永远不会增加超过这个。

方法 sectionHeight 本质上与 sectionSize 相似,不同之处在于,我创建的方法将使用 width 给出给定列标题的边界矩形的高度由 QHeaderView 的 sectionSize 方法给出,-10 用作偏移量。

我创建的最后一个方法是TableView类中的resizeColumns,这个方法连接到sectionResized的{​​{1}}信号。每次调用此方法时(即调整部分的宽度),它会为每个部分(即列)调用 HeaderView,并从中取出最大高度,最后将最大值与 { 中的值进行比较{1}} 的 sectionHeight,以最小值为准,成为 HeaderView 的新的 minimumHeight,因此无论何时更改列宽,标题高度都会无缝调整。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。