PyQt4中如何调整QTableView的垂直表头大小?

7

enter image description here

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

如何在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吗? - Ronikos
抱歉,我是新手,请您详细说明一下?如何使用Qt Designer? - learncode
Qt Designer允许您使用拖放元素创建UI。与手动编写UI相比,它更容易使用,并且可以清理代码。如果这是一个大项目,我强烈建议考虑切换到Qt Designer - 尽管有些东西仍然必须明确编码,具有讽刺意味的是这其中之一。 - Ronikos
3个回答

8
您可以使用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_())

谢谢你的回答!我一直在考虑这个备选方案,即设置一个固定的最大宽度,但那并不是我一直在寻找的。所以你的意思是说用户无法按照自己的意愿调整此标题的大小? - learncode
这是一个大问题,因为某些标题只有一个字符,而某些文件可能有1000个字符,所以我不想用maxWidth来修复大小。 - learncode
1
@VenkataNarsiReddyVaddula。最大宽度不是固定的。当窗口大小调整时,它会在resize事件中进行调整。我使用了表格宽度的百分比,但您可以使用任何方法来设置它。 - ekhumoro
是的,但这个项目的窗口大小是固定的。如果找不到其他替代方案,我会再看几天,然后接受并奖励答案。 - learncode
1
@VenkataNarsiReddyVaddula。好的。我认为你应该在问题中明确表示你想允许用户调整垂直标题的宽度。我认为这仍然是可能的,但需要不同类型的解决方案(可能是自定义标题类)。 - ekhumoro
哇!你不是最棒的吗!这几乎完美地运行了! - learncode

2

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

要修复这种不流畅的行为并实现平滑调整大小,您应该使用全局坐标空间而不是标题视图的本地坐标。

要做到这一点,只需将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()

-1

PyQt倾向于有一些不良的文档,但这个页面提供了关于QTableView类的所有可能信息。

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

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

.setSectionResize()的文档

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

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

.resizeSection()的文档


我已经上传了一张图片,可以帮助您更好地理解问题。另外,QHeaderView没有setSectionResizeMode()函数,我已经尝试了setResizeMode()。 - learncode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接