Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize Vertical Header of QTableView in PyQt4?

enter image description here

I need to reduce the size of first column(the column with vertical headers)

How can I resize a vertical header of QTableView in PyQt4?

I have very large headers and small GUI block to show this table so, please help me!

I am able to resize all the columns but not able to figure out resizing the vertical headers?

I have tried many things like:

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

I want to make the headers which can be resized by the user and has no dependencies on any other parameters of the project like window size, size of other columns....

Can someone help me with this?

like image 719
learncode Avatar asked Dec 22 '16 20:12

learncode


1 Answers

You can limit the size of the vertical header using setMaximWidth, and use setTextElideMode to adjust how the text is cropped.

However, there is no built-in method for making the vertical header width resizable by the user. So as a work-around, you could use the resize-event to adjust the width of the vertical header to a percentage of the total width. That way, resizing the window will also change the width of the vertical header.

Here is a demo script that implements all of that:

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_())

UPDATE:

I had a go at writing a custom header class that implements user resizing of the vertical header width. It almost works, but I cannot find a way to update the view properly whilst dragging with the mouse. Anyway, here is a demo of what I have so far in case anyone can see how to make it work:

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_())
like image 169
ekhumoro Avatar answered Oct 19 '22 11:10

ekhumoro