【问题标题】:Resize Vertical Header of QTableView in PyQt4?在 PyQt4 中调整 QTableView 的垂直标题?
【发布时间】:2017-05-08 13:29:41
【问题描述】:

我需要减小第一列(带有垂直标题的列)的大小

如何在 PyQt4 中调整 QTableView 的垂直标题?

我有非常大的标题和小的 GUI 块来显示这个表,所以请帮助我!

我可以调整所有列的大小,但无法确定调整垂直标题的大小?

我尝试了很多方法,例如:

self.tableView.setColumnWidth(0, 30)  // only able to change the data columns in table not headers

self.tableView.verticalHeader().setResizeMode(QHeaderView.Interactive)  //Able to change the height of headers but not width of them

我想制作可以由用户调整大小的标题,并且不依赖于项目的任何其他参数,如窗口大小、其他列的大小......

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 你考虑过使用Qt Designer吗?
  • 对不起,我是新手,您能详细说明一下吗?如何使用 Qt 设计器?
  • Qt Designer 允许您使用拖放元素创建 UI。它比手动编写 UI 更容易使用,并且可以清理您的代码。如果这是一个大项目,我会彻底建议考虑切换到 Qt Designer - 尽管有些事情仍然需要明确编码,具有讽刺意味的是,这就是其中之一

标签: python resize pyqt4 qtableview qheaderview


【解决方案1】:

Ekhumoro 的解决方案几乎完美无缺。在调整大小期间看到的断断续续的拖动行为与调整大小发生时坐标空间的变化有关。

要修复这种断断续续的行为并平滑调整大小,您应该使用全局坐标空间而不是 headerView 的局部坐标。 为此,只需将 event.x() 替换为 event.globalX()

        #width = event.x() - self._start_position + self._start_width
        width = event.globalX() - self._start_position + self._start_width

            #self._start_position = event.x()
            self._start_position = event.globalX()

我还将几何变化信号更改为从垂直标头而不是水平标头发出。因为实际上改变大小的是垂直标题。然而,在我的测试用例中,我不能说它很重要,但从概念上讲它似乎是正确的。

            #self.geometriesChanged.emit()
            self._vheader.geometriesChanged.emit()

【讨论】:

    【解决方案2】:

    您可以使用setMaximWidth 限制垂直标题的大小,并使用setTextElideMode 调整文本的裁剪方式。

    但是,没有内置的方法可以让用户调整垂直标题的宽度。因此,作为一种解决方法,您可以使用 resize-event 将垂直标题的宽度调整为总宽度的百分比。这样,调整窗口大小也会改变垂直标题的宽度。

    这是一个实现所有这些的演示脚本:

    import sys
    from PyQt4 import QtCore, QtGui
    
    class Window(QtGui.QWidget):
        def __init__(self, rows, columns):
            super(Window, self).__init__()
            self.table = QtGui.QTableView(self)
            self.table.installEventFilter(self)
            self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight)
            model =  QtGui.QStandardItemModel(rows, columns, self.table)
            for row in range(rows):
                item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row)
                model.setVerticalHeaderItem(row, item)
                for column in range(columns):
                    item = QtGui.QStandardItem('(%d, %d)' % (row, column))
                    item.setTextAlignment(QtCore.Qt.AlignCenter)
                    model.setItem(row, column, item)
            self.table.setModel(model)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.table)
    
        def eventFilter(self, source, event):
            if event.type() == QtCore.QEvent.Resize and source is self.table:
                source.verticalHeader().setMaximumWidth(source.width() / 4)
            return super(Window, self).eventFilter(source, event)
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
        window = Window(15, 5)
        window.setGeometry(600, 100, 400, 300)
        window.show()
        sys.exit(app.exec_())
    

    更新

    我尝试编写一个自定义标题类来实现用户调整垂直标题宽度的大小。它几乎可以工作,但我找不到在用鼠标拖动时正确更新视图的方法。无论如何,这是我到目前为止的演示,以防任何人都可以看到如何使它工作:

    import sys
    from PyQt4 import QtCore, QtGui
    
    class HeaderView(QtGui.QHeaderView):
        def __init__(self, table):
            super(HeaderView, self).__init__(QtCore.Qt.Horizontal, table)
            self.setClickable(True)
            self.setHighlightSections(True)
            self.setResizeMode(QtGui.QHeaderView.Interactive)
            self._vheader = table.verticalHeader()
            self._resizing = False
            self._start_position = -1
            self._start_width = -1
    
        def mouseMoveEvent(self, event):
            if self._resizing:
                width = event.x() - self._start_position + self._start_width
                if width > 0:
                    self._vheader.setFixedWidth(width)
                    # TODO: find a proper replacement for this
                    self.geometriesChanged.emit()
            else:
                super(HeaderView, self).mouseMoveEvent(event)
                if 0 <= event.x() <= 3:
                    if not self.testAttribute(QtCore.Qt.WA_SetCursor):
                        self.setCursor(QtCore.Qt.SplitHCursor)
    
        def mousePressEvent(self, event):
            if not self._resizing and event.button() == QtCore.Qt.LeftButton:
                if 0 <= event.x() <= 3:
                    self._start_position = event.x()
                    self._start_width = self._vheader.width()
                    self._resizing = True
                    return
            super(HeaderView, self).mousePressEvent(event)
    
        def mouseReleaseEvent(self, event):
            self._resizing = False
            super(HeaderView, self).mouseReleaseEvent(event)
    
    class Window(QtGui.QWidget):
        def __init__(self, rows, columns):
            super(Window, self).__init__()
            self.table = QtGui.QTableView(self)
            self.table.setHorizontalHeader(HeaderView(self.table))
            self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight)
            model =  QtGui.QStandardItemModel(rows, columns, self.table)
            for row in range(rows):
                item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row)
                item.setToolTip(item.text())
                model.setVerticalHeaderItem(row, item)
                for column in range(columns):
                    item = QtGui.QStandardItem('(%d, %d)' % (row, column))
                    item.setTextAlignment(QtCore.Qt.AlignCenter)
                    model.setItem(row, column, item)
            self.table.setModel(model)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.table)
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
        window = Window(15, 5)
        window.setGeometry(600, 100, 400, 300)
        window.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的回答!我一直在考虑这个关于固定 maxWidth 的替代方案,但这并不是我一直在寻找的。所以你是说用户无法根据自己的意愿调整此标题的大小。
    • 这很重要,因为有些标题只有一个字符,有些文件有大约 1000 个字符,所以我不想用 maxWidth 来固定大小,
    • @VenkataNarsiReddyVaddula。最大宽度不固定。它在调整窗口大小时在 resize-event 中调整。我使用了表格宽度的百分比,但您可以使用任何您喜欢的方法来设置它。
    • 是的,但是项目的窗口大小在这里是固定的。我会寻找几天的另一种选择,如果没有,我会接受并奖励答案。
    • @VenkataNarsiReddyVaddula。好的。我认为您应该在问题中明确表示您希望允许用户调整垂直标题宽度的大小。我认为这仍然是可能的,但需要另一种解决方案(可能是自定义标头类)。
    【解决方案3】:

    PyQt 的文档往往很差,但this page 提供了有关 QTableView 类的所有可能信息。

    我不确定您的具体问题是什么,但是您可以尝试:

    self.tableView.horizontalHeader().setSectionResizeMode(3)
    

    The documentation of .setSectionResize()

    或者,如果您想将每个标题调整为设定的大小,请尝试:

    self.tableView.horizontalHeader().resizeSection(0, pixelSize1)
    self.tableView.horizontalHeader().resizeSection(1, pixelSize2)
    self.tableView.horizontalHeader().resizeSection(2, pixelSize3)
    ...
    

    The documentation of .resizeSection()

    【讨论】:

    • 我上传了一张图片,可以帮助您更好地理解问题。还有QHeaderView没有setSectionResizeMode(),我试过setResizeMode()
    猜你喜欢
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 2016-12-07
    相关资源
    最近更新 更多